From d7233d2f78d40366b1a7ab8cc0aab137c3a40e80 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Sat, 12 Aug 2017 03:21:18 -0300 Subject: [PATCH 01/86] Initial structure new tx pool --- logic/transactions/pool.js | 609 +++++++++++++++++++++++++++ logic/transactions/utils.js | 18 + test/unit/logic/transactions/pool.js | 310 ++++++++++++++ 3 files changed, 937 insertions(+) create mode 100644 logic/transactions/pool.js create mode 100644 logic/transactions/utils.js create mode 100644 test/unit/logic/transactions/pool.js diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js new file mode 100644 index 00000000000..6ff405532b1 --- /dev/null +++ b/logic/transactions/pool.js @@ -0,0 +1,609 @@ +'use strict'; + +var async = require('async'); +var _ = require('lodash'); +var config = require('../../config.json'); +var constants = require('../../helpers/constants.js'); +var jobsQueue = require('../../helpers/jobsQueue.js'); +var transactionTypes = require('../../helpers/transactionTypes.js'); +var utils = require('./utils'); + +// Private fields +var modules, library, self, __private = {}, pool = {}; + +/** + * Initializes variables, sets bundled transaction timer and + * transaction expiry timer. + * @memberof module:transactions + * @class + * @classdesc Main TxPool logic. + * @implements {processPool} + * @param {number} broadcastInterval + * @param {number} releaseLimit + * @param {Transaction} transaction - Logic instance + * @param {bus} bus + * @param {Object} logger + */ +// Constructor +function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, transaction, bus, logger) { + library = { + logger: logger, + bus: bus, + logic: { + transaction: transaction, + }, + config: { + broadcasts: { + broadcastInterval: broadcastInterval, + releaseLimit: releaseLimit, + }, + transactions: { + poolStorageTxsLimit: poolLimit, + poolProcessInterval: poolInterval + } + }, + }; + self = this; + + self.processed = 0; + self.poolStorageTxsLimit = library.config.transactions.poolStorageTxsLimit; + self.poolProcessInterval = library.config.transactions.poolProcessInterval; + self.bundledInterval = library.config.broadcasts.broadcastInterval; + pool = { + unverified: { transactions: [], index: {} }, + verified:{ + pending: { transactions: [], index: {} }, + ready: { transactions: [], index: {} } + } + }; + + // Bundled transaction timer + function nextBundle (cb) { + self.processPool(function (err) { + if (err) { + library.logger.log('processPool transaction timer', err); + } + return setImmediate(cb); + }); + } + + jobsQueue.register('txPoolNextBundle', nextBundle, self.bundledInterval); + +} + +// Public methods +/** + * Bounds input parameters to private variable modules. + * @param {Accounts} accounts + * @param {Transactions} transactions + * @param {Loader} loader + */ +TxPool.prototype.bind = function (accounts, transactions, loader) { + modules = { + accounts: accounts, + transactions: transactions, + loader: loader, + }; +}; + +/** + * Gets unverified, verified.pending and verified.ready indexes and transactions length. + * @return {Object} unverified, pending, ready + */ +TxPool.prototype.getUsage = function () { + return { + unverified: { + indexes: Object.keys(pool.unverified.index).length, + txs: pool.unverified.transactions.length + }, + pending: { + indexes: Object.keys(pool.verified.pending.index).length, + txs: pool.verified.pending.transactions.length + }, + ready: { + indexes: Object.keys(pool.verified.ready.index).length, + txs: pool.verified.ready.transactions.length + } + }; +}; + +/** + * Gets transaction based on transaction id. + * Checks all pool lists: unverified, pending, ready. + * @param {string} id + * @return {Object} tx, status + */ +TxPool.prototype.get = function (id) { + var index = pool.unverified.index[id]; + if (index !== undefined) { + return { + tx: pool.unverified.transactions[index], + status: 'unverified' + }; + } + + index = pool.verified.pending.index[id]; + if (index !== undefined) { + return { + tx: pool.verified.pending.transactions[index], + status: 'pending' + }; + } + + index = pool.verified.ready.index[id]; + if (index !== undefined) { + return { + tx: pool.verified.ready.transactions[index], + status: 'ready' + }; + } + return { + tx: undefined, + status: 'not in pool' + }; +}; + +/** + * Gets ready transactions ordered by fee and received time. + * @param {number} limit + * @return {transaction[]} + */ +TxPool.prototype.getReady = function (limit) { + var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'desc']); + if (limit && limit < r.length) { + r.splice(limit); + } + return r; +}; + +/** + * Gets transactions based on limit and pool list. + * @implements {__private.getTxsFromPoolList} + * @param {string} poolList unverified, pending, ready + * @param {boolean} reverse + * @param {number} limit + * @return {getTransactionList} Calls getTransactionList + */ +TxPool.prototype.getByPoolList = function (poolList, reverse, limit) { + switch (poolList) { + case 'unverified': + return __private.getTxsFromPoolList(pool.unverified.transactions, reverse, limit); + case 'pending': + return __private.getTxsFromPoolList(pool.verified.pending.transactions, reverse, limit); + case 'ready': + return __private.getTxsFromPoolList(pool.verified.ready.transactions, reverse, limit); + default: + return 'Invalid pool list'; + } +}; + +/** + * Checks sender has enough credit to apply transaction. + * @param {transaction} transaction + * @param {address} sender + * @param {function} cb - Callback function. + * @return {setImmediateCallback} err, transactions + */ +TxPool.prototype.checkBalance = function (transaction, sender, cb) { + var balance; + return setImmediate(cb, err, balance); +}; + +/** + * Adds transactions to pool. + * @implements {__private.add} + * @param {transaction[]} transactions + * @param {function} cb - Callback function. + * @return {setImmediateCallback} err, transactions + */ +TxPool.prototype.receiveTransactions = function (transactions, cb) { + async.eachSeries(transactions, function (transaction, cb) { + __private.add(transaction, pool.unverified, cb); + }, function (err) { + return setImmediate(cb, err, transactions.length); + }); +}; + +/** + * Adds transactions to unverified pool list. + * @implements {__private.add} + * @param {transaction} transaction + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +TxPool.prototype.add = function (transactions, cb) { + if (!Array.isArray(transactions)) { + transactions = [transactions]; + } + async.eachSeries(transactions, function (transaction, eachSeriesCb) { + __private.add(transaction, pool.unverified, eachSeriesCb); + }, function (err) { + return setImmediate(cb, err); + }); +}; + +/** + * Adds transactions to verified.ready pool list. + * @implements {__private.addReady} + * @param {transaction} transaction + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +TxPool.prototype.addReady = function (transactions, cb) { + if (!Array.isArray(transactions)) { + transactions = [transactions]; + } + var resetReceivedAt = new Date(); + async.eachSeries(transactions, function (transaction, eachSeriesCb) { + transaction.receivedAt = resetReceivedAt; + __private.addReady(transaction, pool.verified.ready, eachSeriesCb); + }, function (err) { + return setImmediate(cb, err); + }); +}; + +/** + * Deletes transaction from pool list. + * @implements {__private.delete} + * @param {transaction} transaction + * @return {Array} names of cleared lists + */ +TxPool.prototype.delete = function (transaction) { + var clearedList = []; + var poolList = ['unverified','pending','ready']; + + [pool.unverified, pool.verified.pending, pool.verified.ready].forEach(function (list, index) { + if (__private.delete(transaction.id, list)) { + clearedList.push(poolList[index]); + } + }); + if (clearedList.length > 0) { + if (clearedList.length > 1) { + library.logger.debug(['Cleared duplicated tx in pool list:', clearedList, 'txid:', transaction.id].join(' ')); + } + } + return clearedList; +}; + +/** + * Pulls transactions from unverified, perform verifications and if successful + * push to either verified.pending (when tx is multisign or timestamp is in + * future) or verified.ready otherwise. + * @implements {__private.delete} + * @implements {processVerifyTransaction} + * @implements {removeUnconfirmedTransaction} + * @param {function} cb + * @return {setImmediateCallback} err | cb + */ +TxPool.prototype.processPool = function (cb) { + async.series({ + expireTransactions: function (seriesCb) { + __private.expireTransactions(function (err) { + if (err) { + library.logger.log('Transaction expiry timer', err); + } + return setImmediate(seriesCb); + }); + }, + processUnverified: function (seriesCb) { + async.eachSeries(pool.unverified.transactions, function (transaction, eachSeriesCb) { + __private.delete(transaction.id, pool.unverified); + __private.processUnverifiedTransaction(transaction, true, function (err, sender) { + if (err) { + library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); + return setImmediate(eachSeriesCb); + } + self.checkBalance(transaction, sender, function (err) { + if (err) { + library.logger.error('Failed to check balance transaction: ' + transaction.id, err); + } + transaction.receivedAt = new Date(); + if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures || transaction.receivedAt < transaction.timestamp)) { + __private.add(transaction, pool.verified.pending, eachSeriesCb); + } else { + // check transaction and if ok add to verified.ready + __private.add(transaction, pool.verified.ready, eachSeriesCb); + } + }); + }); + }, function (err) { + return setImmediate(seriesCb, err); + }); + }, + processPending: function (seriesCb) { + // process pool.verified.pending (multisig txs signs), and take care + // about moving transactions from `verified.pending` to `verified.ready` + async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { + __private.delete(transaction.id, pool.verified.pending); + __private.add(transaction, pool.verified.ready, eachSeriesCb); + }, function (err) { + return setImmediate(seriesCb, err); + }); + }, + reindexQueues: function (seriesCb) { + if (self.processed > 1000) { + __private.reindexQueues(); + self.processed = 0; + } + } + }, function (err) { + return setImmediate(cb, err); + }); +}; + +// Private +/** + * Gets reversed or limited transactions from input parameter. + * @private + * @param {transaction[]} transactions + * @param {boolean} reverse + * @param {number} limit + * @return {transaction[]} + */ +__private.getTxsFromPoolList = function (transactions, reverse, limit) { + var txs = transactions.filter(Boolean); + + if (reverse) { + txs = txs.reverse(); + } + if (limit) { + txs.splice(limit); + } + + return txs; +}; + +/** + * Returns true if the id is present in at least one of the index values. + * Index values: unverified, verified.pending, verified.ready. + * @param {string} id + * @return {boolean} + */ +__private.transactionInPool = function (id) { + return [ + pool.unverified.index[id], + pool.verified.pending.index[id], + pool.verified.ready.index[id] + ].filter(function (inList) { + return inList !== undefined; + }).length > 0; +}; + +/** + * Adds transactions to pool list. + * Checks if tx is in pool. Checks pool limit. + * @implements {__private.transactionInPool} + * @param {transaction} transaction + * @param {Object} poolList + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.add = function (transaction, poolList, cb) { + if (__private.countTxsPool() >= self.poolStorageTxsLimit) { + return setImmediate(cb, 'Transaction pool is full'); + } + if (__private.transactionInPool(transaction.id)) { + return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); + } else { + poolList.transactions.push(transaction); + var index = poolList.transactions.indexOf(transaction); + poolList.index[transaction.id] = index; + self.processed++; + return setImmediate(cb); + } +}; + +/** + * Adds transactions to pool list. + * Clear transaction if is in pool. + * @implements {__private.transactionInPool} + * @param {transaction} transaction + * @param {Object} poolList + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.addReady = function (transaction, poolList, cb) { + self.delete(transaction); + poolList.transactions.push(transaction); + var index = poolList.transactions.indexOf(transaction); + poolList.index[transaction.id] = index; + self.processed++; + return setImmediate(cb); +}; + +/** + * Deletes id from pool list index. + * @param {string} id + * @param {Object} poolList + * @return {boolean} true if transaction id is on the list and was deleted + */ +__private.delete = function (id, poolList) { + var index = poolList.index[id]; + + if (index !== undefined) { + poolList.transactions[index] = false; + delete poolList.index[id]; + return true; + } + return false; +}; + +/** + * Sums unverified, verified.pending and verified.ready transactions length. + * @return {Number} unverified, pending, ready + */ +__private.countTxsPool = function () { + var totalPool = self.getUsage(); + + return totalPool.unverified.indexes + totalPool.pending.indexes + totalPool.ready.indexes; +}; + +/** + * Expires transactions. + * @implements {__private.expireTxsFromList} + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | ids[] + */ +__private.expireTransactions = function (cb) { + var ids = []; + + async.waterfall([ + function (seriesCb) { + __private.expireTxsFromList(pool.unverified, ids, seriesCb); + }, + function (res, seriesCb) { + __private.expireTxsFromList(pool.verified.pending, ids, seriesCb); + }, + function (res, seriesCb) { + __private.expireTxsFromList(pool.verified.ready, ids, seriesCb); + } + ], function (err, ids) { + return setImmediate(cb, err, ids); + }); +}; + +/** + * Regenerates pool lists indexes and clears deleted transactions. + */ +__private.reindexQueues = function () { + [pool.unverified, pool.verified.pending, pool.verified.ready].forEach(function (list) { + list.index = {}; + list.transactions = list.transactions.filter(Boolean); + list.transactions.forEach(function (transaction) { + var index = list.transactions.indexOf(transaction); + list.index[transaction.id] = index; + }); + }); +}; + +/** + * Removes transactions if expired from pool list. + * @private + * @implements {__private.transactionTimeOut} + * @implements {__private.delete} + * @param {Object[]} poolList + * @param {string[]} parentIds + * @param {function} cb - Callback function + * @return {setImmediateCallback} error | ids[] + */ +__private.expireTxsFromList = function (poolList, parentIds, cb) { + var ids = []; + + async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { + if (!transaction) { + return setImmediate(eachSeriesCb); + } + + var timeNow = Math.floor(Date.now() / 1000); + var timeOut = __private.transactionTimeOut(transaction); + // transaction.receivedAt is instance of Date + console.log("expireTransactions - transaction.receivedAt",transaction.receivedAt); + var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); + + if (seconds > timeOut) { + ids.push(transaction.id); + __private.delete(poolList, transaction.id); + library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); + return setImmediate(eachSeriesCb); + } else { + return setImmediate(eachSeriesCb); + } + }, function (err) { + return setImmediate(cb, err, ids.concat(parentIds)); + }); +}; + +/** + * Calculates timeout based on transaction. + * @private + * @param {transaction} transaction + * @return {number} timeOut + */ +__private.transactionTimeOut = function (transaction) { + if (transaction.type === transactionTypes.MULTI) { + return (transaction.asset.multisignature.lifetime * 3600); + } else if (Array.isArray(transaction.signatures)) { + return (constants.unconfirmedTransactionTimeOut * 8); + } else { + return (constants.unconfirmedTransactionTimeOut); + } +}; + +/** + * Gets sender account, verifies multisignatures, gets requester, + * process transaction and verifies. + * @private + * @implements {accounts.setAccountAndGet} + * @implements {accounts.getAccount} + * @implements {logic.transaction.process} + * @implements {logic.transaction.verify} + * @param {transaction} transaction + * @param {object} broadcast + * @param {function} cb - Callback function + * @returns {setImmediateCallback} errors | sender + */ +__private.processUnverifiedTransaction = function (transaction, broadcast, cb) { + if (!transaction) { + return setImmediate(cb, 'Missing transaction'); + } + + async.waterfall([ + function setAccountAndGet (waterCb) { + modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); + }, + function getRequester (sender, waterCb) { + var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; + + if (multisignatures) { + transaction.signatures = transaction.signatures || []; + } + + if (sender && transaction.requesterPublicKey && multisignatures) { + modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { + if (!requester) { + return setImmediate(waterCb, 'Requester not found'); + } else { + return setImmediate(waterCb, null, sender, requester); + } + }); + } else { + return setImmediate(waterCb, null, sender, null); + } + }, + function processTransaction (sender, requester, waterCb) { + library.logic.transaction.process(transaction, sender, requester, function (err) { + if (err) { + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, sender); + } + }); + }, + function normalizeTransaction (sender, waterCb) { + try { + transaction = library.logic.transaction.objectNormalize(transaction); + return setImmediate(waterCb, null, sender); + } catch (err) { + return setImmediate(waterCb, err); + } + }, + function verifyTransaction (sender, waterCb) { + library.logic.transaction.verify(transaction, sender, function (err) { + if (err) { + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, sender); + } + }); + } + ], function (err, sender) { + if (!err) { + library.bus.message('unconfirmedTransaction', transaction, broadcast); + } + + return setImmediate(cb, err, sender); + }); +}; + +// Export +module.exports = TxPool; \ No newline at end of file diff --git a/logic/transactions/utils.js b/logic/transactions/utils.js new file mode 100644 index 00000000000..e5fba09fb09 --- /dev/null +++ b/logic/transactions/utils.js @@ -0,0 +1,18 @@ +'use strict'; + +var BSON = require('bson'); + +var bson = new BSON(); + +exports.pack = pack; +exports.unpack = unpack; + +function pack (data) { + return bson.serialize(data); +} + +function unpack (data) { + return bson.deserialize(data); +} + + \ No newline at end of file diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js new file mode 100644 index 00000000000..7387dd1d501 --- /dev/null +++ b/test/unit/logic/transactions/pool.js @@ -0,0 +1,310 @@ +'use strict'; + +var expect = require('chai').expect; + +var modulesLoader = require('../../../common/initModule').modulesLoader; +var TxPool = require('../../../../logic/transactions/pool.js'); +var Transaction = require('../../../../logic/transaction.js'); + +var transactions = [ + /* type: 0 - Transmit funds */ + { + 'type': 0, + 'amount': 100000000, + 'fee': 10000000, + 'timestamp': 37943880, + 'recipientId': '16313739661670634666L', + 'senderId': '2737453412992791987L', + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7249285091378090017' + }, + /* type: 1 - Register a second signature */ + { + 'type': 1, + 'amount': 0, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'timestamp': 37943881, + 'recipientId': null, + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7249285091378090018', + 'fee': 500000000, + 'senderId': '2737453412992791987L', + 'asset': { + 'signature': { + 'publicKey': 'The public key associated with the second passphrase' + } + } + }, + /* type: 2 - Register a delegate */ + { + 'type': 2, + 'amount': 0, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'timestamp': 37943882, + 'recipientId': null, + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7249285091378090019', + 'fee': 500000000, + 'senderId': '2737453412992791987L', + 'asset': { + 'delegate': { + 'username': 'The chosen username', + 'publicKey': 'The public key associated with the second passphrase' + } + } + }, + /* type: 3 - Submit votes */ + { + 'type': 3, + 'amount': 30000, + 'fee': 3, + 'id': '7249285091378090020' + }, + /* type: 4 - Multisignature registration */ + { + 'type': 4, + 'amount': 40000, + 'fee': 4, + 'id': '7249285091378090021' + }, + /* type: 0 - Transmit funds Account does not have enough LSK*/ + { + 'type': 0, + 'amount': 10000000000000000, + 'fee': 10000000, + 'timestamp': 37943840, + 'recipientId': '16313739661670634666L', + 'senderId': '2737453412992791987L', + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7249285091378090022' + }, +]; +var extraTransaction = { + 'type': 0, + 'amount': 100000000, + 'fee': 10000000, + 'timestamp': 37943880, + 'recipientId': '16313739661670634666L', + 'senderId': '2737453412992791987L', + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7249285091378090023' +}; +describe('txPool', function () { + + var accounts; + var txPool; + var poolTotals; + var txReady; + var poolStorageTxsLimit; + + before(function (done) { + modulesLoader.initLogic(Transaction, modulesLoader.scope, function (err, __trsLogic) { + if (err) { + return done(err); + } + modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; + modulesLoader.scope.config.transactions.poolProcessInterval = 6000; + poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; + txPool = new TxPool( + modulesLoader.scope.config.broadcasts.broadcastInterval, + modulesLoader.scope.config.broadcasts.releaseLimit, + modulesLoader.scope.config.transactions.poolStorageTxsLimit, + modulesLoader.scope.config.transactions.poolProcessInterval, + __trsLogic, + modulesLoader.scope.bus, + modulesLoader.scope.logger + ); + + modulesLoader.initModules([ + {accounts: require('../../../../modules/accounts')}, + ], [ + {'transaction': require('../../../../logic/transaction')}, + {'account': require('../../../../logic/account')} + ], {}, function (err, __modules) { + if (err) { + return done(err); + } + txPool.bind( + __modules.accounts, + null, + __modules.loader + ); + + done(); + }); + }); + }); + + describe('unverified', function () { + + describe('method add', function () { + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified.indexes).to.be.a('number'); + expect(totals.pending.indexes).to.be.a('number'); + expect(totals.ready.indexes).to.be.a('number'); + expect(totals.unverified.txs).to.be.a('number'); + expect(totals.pending.txs).to.be.a('number'); + expect(totals.ready.txs).to.be.a('number'); + poolTotals = totals; + done(); + }); + + it('should be ok when add transaction type 0 to unverified', function (done) { + txPool.add(transactions[0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when check unverified value increased in 1', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified.indexes).to.equal(poolTotals.unverified.indexes + 1); + expect(totals.unverified.txs).to.equal(poolTotals.unverified.txs + 1); + poolTotals = totals; + done(); + }); + + it('should fail when add same transaction type 0 to unverified', function (done) { + txPool.add(transactions[0], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: 7249285091378090017'); + done(); + }); + }); + + it('should be ok when add transactions to fill pool storage', function (done) { + var trx = transactions.slice(1,transactions.length) + txPool.add(trx, function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when pool totals are equal to pool storage limit', function (done) { + var totals = txPool.getUsage(); + var currentStorage = totals.unverified.indexes + totals.pending.indexes + totals.ready.indexes; + expect(totals).to.be.an('object'); + expect(currentStorage).to.equal(poolStorageTxsLimit); + poolTotals = totals; + done(); + }); + + it('should fail when add transaction and pool storage is full', function (done) { + txPool.add(extraTransaction, function (err, cbtx) { + expect(err).to.equal('Transaction pool is full'); + done(); + }); + }); + }); + + describe('method delete', function () { + + it('should be ok when delete a transaction from unverified', function (done) { + var deleteTx = txPool.delete(transactions[0]); + + expect(deleteTx).to.be.an('array').that.is.not.empty; + expect(deleteTx.length).to.equal(1); + expect(deleteTx[0]).to.equal('unverified'); + done(); + }); + + it('should be ok when check unverified value decreased in 1', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified.indexes).to.equal(poolTotals.unverified.indexes - 1); + expect(totals.unverified.txs).to.equal(poolTotals.unverified.txs); + poolTotals = totals; + done(); + }); + }); + }); + + describe('ready', function () { + describe('method addReady/getReady', function () { + + it('should be ok when add transactions to ready', function (done) { + txPool.addReady(transactions, function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + poolTotals.ready.indexes += transactions.length; + poolTotals.ready.txs += transactions.length; + done(); + }); + }); + + it('should be ok when get transactions from ready', function (done) { + var readyTxs = txPool.getReady(); + expect(readyTxs[0].fee).to.be.at.least(readyTxs[1].fee); + expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); + expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); + done(); + }); + + it('should be ok when delete transaction from ready', function (done) { + var deleteTx = txPool.delete(transactions[0]); + + expect(deleteTx).to.be.an('array').that.is.not.empty; + expect(deleteTx.length).to.equal(1); + expect(deleteTx[0]).to.equal('ready'); + done(); + }); + + it('should be ok when check ready value decreased in 1', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.ready.indexes).to.equal(poolTotals.ready.indexes - 1); + expect(totals.ready.txs).to.equal(poolTotals.ready.txs); + poolTotals = totals; + done(); + + }); + }); + }); + + describe('process worker', function() { + + }); + + describe('transport', function() { + + }); + + describe('getters', function() { + + it('should be ok when get all transactions from unverified', function (done) { + var txs = txPool.getByPoolList('unverified'); + expect(txs.length).to.equal(0) + done(); + }); + + it('should be ok when get all transactions from pending', function (done) { + var txs = txPool.getByPoolList('pending'); + expect(txs.length).to.equal(0) + done(); + }); + + it('should be ok when get all transactions from ready', function (done) { + var txs = txPool.getByPoolList('ready'); + expect(txs.length).to.equal(5) + done(); + }); + }); +}); \ No newline at end of file From 6d367b7e899490ae855828526441681d0611da19 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Sat, 12 Aug 2017 15:41:53 -0300 Subject: [PATCH 02/86] Adjust descriptions --- logic/transactions/pool.js | 6 ++-- test/unit/logic/transactions/pool.js | 46 ++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 6ff405532b1..3804fe3f7c5 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -139,7 +139,7 @@ TxPool.prototype.get = function (id) { } return { tx: undefined, - status: 'not in pool' + status: 'Not in pool' }; }; @@ -162,7 +162,7 @@ TxPool.prototype.getReady = function (limit) { * @param {string} poolList unverified, pending, ready * @param {boolean} reverse * @param {number} limit - * @return {getTransactionList} Calls getTransactionList + * @return {[transactins]} transactions in pool list filter by limit. */ TxPool.prototype.getByPoolList = function (poolList, reverse, limit) { switch (poolList) { @@ -429,7 +429,7 @@ __private.delete = function (id, poolList) { }; /** - * Sums unverified, verified.pending and verified.ready transactions length. + * Sums unverified, verified.pending and verified.ready indexes length. * @return {Number} unverified, pending, ready */ __private.countTxsPool = function () { diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 7387dd1d501..5602fa09985 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -279,32 +279,66 @@ describe('txPool', function () { }); }); - describe('process worker', function() { + describe('transport', function() { }); - - describe('transport', function() { + + describe('process worker', function() { }); describe('getters', function() { - it('should be ok when get all transactions from unverified', function (done) { + xit('should be ok when get transaction by id from unverified list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('unverified'); + done(); + }); + + xit('should be ok when get transaction by id from pending list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('pending'); + done(); + }); + + it('should be ok when get transaction by id from ready list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('ready'); + done(); + }); + + it('should fail when get transaction by id that is not in the pool', function (done) { + var transaction = txPool.get(transactions[0].id); + expect(transaction.tx).to.be.undefined; + expect(transaction.status).to.equal('Not in pool'); + done(); + }); + + it('should be ok when get all transactions from unverified list', function (done) { var txs = txPool.getByPoolList('unverified'); expect(txs.length).to.equal(0) done(); }); - it('should be ok when get all transactions from pending', function (done) { + it('should be ok when get all transactions from pending list', function (done) { var txs = txPool.getByPoolList('pending'); expect(txs.length).to.equal(0) done(); }); - it('should be ok when get all transactions from ready', function (done) { + it('should be ok when get all transactions from ready list', function (done) { var txs = txPool.getByPoolList('ready'); expect(txs.length).to.equal(5) done(); }); + + it('should fail when get all transactions from unknown list', function (done) { + var txs = txPool.getByPoolList('unknown'); + expect(txs).to.equal('Invalid pool list'); + done(); + }); }); }); \ No newline at end of file From 456fac99be7ddae6be479eebddc298ceca36b3a5 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Tue, 15 Aug 2017 12:32:49 -0300 Subject: [PATCH 03/86] Get by account and public key --- logic/transactions/pool.js | 97 +++++++++++ logic/transactions/utils.js | 2 - test/unit/logic/transactions/pool.js | 235 ++++++++++++++++++++++----- 3 files changed, 290 insertions(+), 44 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 3804fe3f7c5..74e8339122f 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -177,6 +177,52 @@ TxPool.prototype.getByPoolList = function (poolList, reverse, limit) { } }; +/** + * Gets transactions from pool based on account address and entity: sender, recipient. + * @implements {__private.getAllPoolTxsByFilter} + * @param {account} id valid account address + * @param {string} entity sender, recipient + * @return {getTransactionList} Calls getTransactionList + */ +TxPool.prototype.getByAccountId = function (id, entity) { + var err = __private.checkAddress(id); + if (err) { + return err; + } + switch (entity) { + case 'sender': + return __private.getAllPoolTxsByFilter({'senderId': id}); + case 'recipient': + return __private.getAllPoolTxsByFilter({'recipientId': id}); + default: + return 'Invalid entity account address'; + } +}; + +/** + * Gets transactions from pool based on publicKey and entity: sender, recipient. + * @implements {__private.getAllPoolTxsByFilter} + * @param {string} publicKey + * @param {string} entity sender, requester + * @return {getTransactionList} Calls getTransactionList + */ +TxPool.prototype.getByAccountPublicKey = function (publicKey, entity) { + var err = __private.checkPublicKey(publicKey); + if (err) { + return err; + } + switch (entity) { + case 'sender': + return __private.getAllPoolTxsByFilter({'senderPublicKey': publicKey}); + case 'requester': + return __private.getAllPoolTxsByFilter({'requesterPublicKey': publicKey}); + default: + return 'Invalid entity for public key'; + } +}; + + + /** * Checks sender has enough credit to apply transaction. * @param {transaction} transaction @@ -353,6 +399,22 @@ __private.getTxsFromPoolList = function (transactions, reverse, limit) { return txs; }; +/** + * Gets transactions from pool list based on filter. + * @private + * @param {Object} filter search criteria + * @return {Objetc} transactions by pool list + */ +__private.getAllPoolTxsByFilter = function (filter) { + var txs = { + unverified: _.filter(pool.unverified, filter), + pending: _.filter(pool.verified.pending, filter), + ready: _.filter(pool.verified.ready, filter) + }; + + return txs; +}; + /** * Returns true if the id is present in at least one of the index values. * Index values: unverified, verified.pending, verified.ready. @@ -369,6 +431,41 @@ __private.transactionInPool = function (id) { }).length > 0; }; +/** + * Validates address. + * @param {string} address + * @return {null|err} + * @todo check address against mem_accounts + */ +__private.checkAddress = function (address) { + if (address.charAt(address.length-1) !== 'L') { + return 'Invalid address, last char must be "L"'; + } + if (address.slice(0,address.length-1).match(/^[0-9]+$/) === null) { + return 'Invalid address, must be numbers'; + } + return null; +}; + +/** + * Validates publicKey. + * @param {string} publicKey + * @return {null|err} + * @todo check publicKey against mem_accounts + */ +__private.checkPublicKey = function (publicKey) { + if (typeof publicKey !== 'string') { + return 'Invalid public key, must be a string'; + } + if (publicKey.length !== 64) { + return 'Invalid public key, must be 64 characters long'; + } + if (publicKey.match(/^[0-9A-Fa-f]+$/) === null) { + return 'Invalid public key, must be a hex string'; + } + return null; +}; + /** * Adds transactions to pool list. * Checks if tx is in pool. Checks pool limit. diff --git a/logic/transactions/utils.js b/logic/transactions/utils.js index e5fba09fb09..47f37d798cb 100644 --- a/logic/transactions/utils.js +++ b/logic/transactions/utils.js @@ -14,5 +14,3 @@ function pack (data) { function unpack (data) { return bson.deserialize(data); } - - \ No newline at end of file diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 5602fa09985..d21be15ef89 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -5,6 +5,7 @@ var expect = require('chai').expect; var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); +var utils = require('../../../../logic/transactions/utils.js'); var transactions = [ /* type: 0 - Transmit funds */ @@ -279,8 +280,28 @@ describe('txPool', function () { }); }); - describe('transport', function() { + describe('broadcast transactions', function() { + var broadcastTx; + it('should be ok when serialize transaction (pack)', function (done) { + broadcastTx = utils.pack(transactions[0]); + expect(broadcastTx).that.is.an('Uint8Array'); + done(); + }); + + it('should be ok when unpacked size is greater than packed size', function (done) { + var packedLenght = Buffer.from(broadcastTx).length; + var unpackedLenght = Buffer.from(JSON.stringify(transactions[0])).length; + + expect(unpackedLenght).to.be.at.least(packedLenght); + done(); + }); + + it('should be ok when deserialize transaction (unpack)', function (done) { + broadcastTx = utils.unpack(broadcastTx); + expect(broadcastTx).to.deep.equal(transactions[0]); + done(); + }); }); describe('process worker', function() { @@ -289,56 +310,186 @@ describe('txPool', function () { describe('getters', function() { - xit('should be ok when get transaction by id from unverified list', function (done) { - var transaction = txPool.get(transactions[5].id); - expect(transaction.tx).to.deep.equal(transactions[5]); - expect(transaction.status).to.equal('unverified'); - done(); - }); + describe('get transaction by id', function() { - xit('should be ok when get transaction by id from pending list', function (done) { - var transaction = txPool.get(transactions[5].id); - expect(transaction.tx).to.deep.equal(transactions[5]); - expect(transaction.status).to.equal('pending'); - done(); - }); + xit('should be ok when transaction is in unverified list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('unverified'); + done(); + }); - it('should be ok when get transaction by id from ready list', function (done) { - var transaction = txPool.get(transactions[5].id); - expect(transaction.tx).to.deep.equal(transactions[5]); - expect(transaction.status).to.equal('ready'); - done(); - }); + xit('should be ok when transaction is in pending list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('pending'); + done(); + }); - it('should fail when get transaction by id that is not in the pool', function (done) { - var transaction = txPool.get(transactions[0].id); - expect(transaction.tx).to.be.undefined; - expect(transaction.status).to.equal('Not in pool'); - done(); - }); + it('should be ok when transaction is in ready list', function (done) { + var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); + expect(transaction.status).to.equal('ready'); + done(); + }); - it('should be ok when get all transactions from unverified list', function (done) { - var txs = txPool.getByPoolList('unverified'); - expect(txs.length).to.equal(0) - done(); + it('should fail when transaction is not in the pool', function (done) { + var transaction = txPool.get(transactions[0].id); + expect(transaction.tx).to.be.undefined; + expect(transaction.status).to.equal('Not in pool'); + done(); + }); }); - it('should be ok when get all transactions from pending list', function (done) { - var txs = txPool.getByPoolList('pending'); - expect(txs.length).to.equal(0) - done(); + describe('get all by pool list', function() { + + it('should be ok when pool list is unverified', function (done) { + var txs = txPool.getByPoolList('unverified'); + expect(txs.length).to.equal(0) + done(); + }); + + it('should be ok when pool list is pending', function (done) { + var txs = txPool.getByPoolList('pending'); + expect(txs.length).to.equal(0) + done(); + }); + + it('should be ok when pool list is ready', function (done) { + var txs = txPool.getByPoolList('ready'); + expect(txs.length).to.equal(5) + done(); + }); + + it('should fail when pool list is invalid', function (done) { + var txs = txPool.getByPoolList('unknown'); + expect(txs).to.equal('Invalid pool list'); + done(); + }); }); - - it('should be ok when get all transactions from ready list', function (done) { - var txs = txPool.getByPoolList('ready'); - expect(txs.length).to.equal(5) - done(); + + describe('get all by id (address)', function() { + + it('should be ok when sender account is valid', function (done) { + var txs = txPool.getByAccountId('2737453412992791987L', 'sender'); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should fail when sender account last char is not L', function (done) { + var txs = txPool.getByAccountId('2737453412992791987M', 'sender'); + + expect(txs).to.equal('Invalid address, last char must be "L"'); + done(); + }); + + it('should fail when sender account main body is not a number', function (done) { + var txs = txPool.getByAccountId('A737453412992791987L', 'sender'); + + expect(txs).to.equal('Invalid address, must be numbers'); + done(); + }); + + it('should be ok when recipient account is valid', function (done) { + var txs = txPool.getByAccountId('16313739661670634666L', 'recipient'); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should fail when recipient account last char is not L', function (done) { + var txs = txPool.getByAccountId('16313739661670634666M', 'recipient'); + + expect(txs).to.equal('Invalid address, last char must be "L"'); + done(); + }); + + it('should fail when recipient account main body is not a number', function (done) { + var txs = txPool.getByAccountId('A6313739661670634666L', 'recipient'); + + expect(txs).to.equal('Invalid address, must be numbers'); + done(); + }); }); - it('should fail when get all transactions from unknown list', function (done) { - var txs = txPool.getByPoolList('unknown'); - expect(txs).to.equal('Invalid pool list'); - done(); + describe('get all by publicKey', function() { + it('should be ok when sender publicKey is valid', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'sender'); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should fail when sender publicKey is not a string', function (done) { + var txs = txPool.getByAccountPublicKey(123456789, 'sender'); + + expect(txs).to.equal('Invalid public key, must be a string'); + done(); + }); + + it('should fail when sender publicKey is less than 64 characters long', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7', 'sender'); + + expect(txs).to.equal('Invalid public key, must be 64 characters long'); + done(); + }); + + it('should fail when sender publicKey is greater than 64 characters long', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1', 'sender'); + + expect(txs).to.equal('Invalid public key, must be 64 characters long'); + done(); + }); + + it('should fail when sender publicKey is not hex string', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2c3po', 'sender'); + + expect(txs).to.equal('Invalid public key, must be a hex string'); + done(); + }); + it('should be ok when requester publicKey is valid', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'requester'); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should fail when requester publicKey is not a string', function (done) { + var txs = txPool.getByAccountPublicKey(123456789, 'requester'); + + expect(txs).to.equal('Invalid public key, must be a string'); + done(); + }); + + it('should fail when requester publicKey is less than 64 characters long', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7', 'requester'); + + expect(txs).to.equal('Invalid public key, must be 64 characters long'); + done(); + }); + + it('should fail when requester publicKey is greater than 64 characters long', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1', 'requester'); + + expect(txs).to.equal('Invalid public key, must be 64 characters long'); + done(); + }); + + it('should fail when requester publicKey is not hex string', function (done) { + var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2r2d2', 'requester'); + + expect(txs).to.equal('Invalid public key, must be a hex string'); + done(); + }); }); }); }); \ No newline at end of file From e6248a8eee0439565ce7ef397622d1496f546c6e Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Tue, 15 Aug 2017 17:03:13 -0300 Subject: [PATCH 04/86] Move tx utils to bson helper --- helpers/bson.js | 35 ++++++++++++++++++++++++++++ logic/transactions/pool.js | 1 - logic/transactions/utils.js | 16 ------------- test/unit/logic/transactions/pool.js | 18 +++++++------- 4 files changed, 44 insertions(+), 26 deletions(-) create mode 100644 helpers/bson.js delete mode 100644 logic/transactions/utils.js diff --git a/helpers/bson.js b/helpers/bson.js new file mode 100644 index 00000000000..cfda2eebacc --- /dev/null +++ b/helpers/bson.js @@ -0,0 +1,35 @@ +'use strict'; + +var BSON = require('bson'); + +var bson = new BSON(); + +/** + * BSON wrapper. + * @memberof module:helpers + * @requires bson + * @namespace + */ +var bs = {}; + +/** + * Serializes input data. + * @implements {bson} + * @param {Object} data + * @return {Buffer} + */ +bs.serialize = function (data) { + return bson.serialize(data); +}; + +/** + * Deserializes input data. + * @implements {bson} + * @param {Buffer} data + * @return {Object} + */ +bs.deserialize = function (data) { + return bson.deserialize(data); +}; + +module.exports = bs; \ No newline at end of file diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 74e8339122f..ab888ac01fc 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -6,7 +6,6 @@ var config = require('../../config.json'); var constants = require('../../helpers/constants.js'); var jobsQueue = require('../../helpers/jobsQueue.js'); var transactionTypes = require('../../helpers/transactionTypes.js'); -var utils = require('./utils'); // Private fields var modules, library, self, __private = {}, pool = {}; diff --git a/logic/transactions/utils.js b/logic/transactions/utils.js deleted file mode 100644 index 47f37d798cb..00000000000 --- a/logic/transactions/utils.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -var BSON = require('bson'); - -var bson = new BSON(); - -exports.pack = pack; -exports.unpack = unpack; - -function pack (data) { - return bson.serialize(data); -} - -function unpack (data) { - return bson.deserialize(data); -} diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index d21be15ef89..52df8855eaa 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -5,7 +5,7 @@ var expect = require('chai').expect; var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); -var utils = require('../../../../logic/transactions/utils.js'); +var bson = require('../../../../helpers/bson.js'); var transactions = [ /* type: 0 - Transmit funds */ @@ -283,22 +283,22 @@ describe('txPool', function () { describe('broadcast transactions', function() { var broadcastTx; - it('should be ok when serialize transaction (pack)', function (done) { - broadcastTx = utils.pack(transactions[0]); + it('should be ok when serialize transaction', function (done) { + broadcastTx = bson.serialize(transactions[0]); expect(broadcastTx).that.is.an('Uint8Array'); done(); }); - it('should be ok when unpacked size is greater than packed size', function (done) { - var packedLenght = Buffer.from(broadcastTx).length; - var unpackedLenght = Buffer.from(JSON.stringify(transactions[0])).length; + it('should be ok when deserialized size is greater than serialized size', function (done) { + var serializedLenght = Buffer.from(broadcastTx).length; + var deserializedLenght = Buffer.from(JSON.stringify(transactions[0])).length; - expect(unpackedLenght).to.be.at.least(packedLenght); + expect(deserializedLenght).to.be.at.least(serializedLenght); done(); }); - it('should be ok when deserialize transaction (unpack)', function (done) { - broadcastTx = utils.unpack(broadcastTx); + it('should be ok when deserialize transaction', function (done) { + broadcastTx = bson.deserialize(broadcastTx); expect(broadcastTx).to.deep.equal(transactions[0]); done(); }); From 4f45d330c3bb5befa2ae9bdc0c10b334874012aa Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Tue, 15 Aug 2017 17:28:54 -0300 Subject: [PATCH 05/86] Eslint --- logic/transactions/pool.js | 4 +- test/unit/logic/transactions/pool.js | 56 ++++++++++++++-------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index ab888ac01fc..aa36e1190ba 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -231,7 +231,7 @@ TxPool.prototype.getByAccountPublicKey = function (publicKey, entity) { */ TxPool.prototype.checkBalance = function (transaction, sender, cb) { var balance; - return setImmediate(cb, err, balance); + return setImmediate(cb, balance); }; /** @@ -593,7 +593,7 @@ __private.expireTxsFromList = function (poolList, parentIds, cb) { var timeNow = Math.floor(Date.now() / 1000); var timeOut = __private.transactionTimeOut(transaction); // transaction.receivedAt is instance of Date - console.log("expireTransactions - transaction.receivedAt",transaction.receivedAt); + console.log('expireTransactions - transaction.receivedAt',transaction.receivedAt); var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); if (seconds > timeOut) { diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 52df8855eaa..f9db6bf66a9 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -32,9 +32,9 @@ var transactions = [ 'fee': 500000000, 'senderId': '2737453412992791987L', 'asset': { - 'signature': { - 'publicKey': 'The public key associated with the second passphrase' - } + 'signature': { + 'publicKey': 'The public key associated with the second passphrase' + } } }, /* type: 2 - Register a delegate */ @@ -49,10 +49,10 @@ var transactions = [ 'fee': 500000000, 'senderId': '2737453412992791987L', 'asset': { - 'delegate': { - 'username': 'The chosen username', - 'publicKey': 'The public key associated with the second passphrase' - } + 'delegate': { + 'username': 'The chosen username', + 'publicKey': 'The public key associated with the second passphrase' + } } }, /* type: 3 - Submit votes */ @@ -110,14 +110,14 @@ describe('txPool', function () { modulesLoader.scope.config.transactions.poolProcessInterval = 6000; poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; txPool = new TxPool( - modulesLoader.scope.config.broadcasts.broadcastInterval, - modulesLoader.scope.config.broadcasts.releaseLimit, - modulesLoader.scope.config.transactions.poolStorageTxsLimit, - modulesLoader.scope.config.transactions.poolProcessInterval, - __trsLogic, - modulesLoader.scope.bus, - modulesLoader.scope.logger - ); + modulesLoader.scope.config.broadcasts.broadcastInterval, + modulesLoader.scope.config.broadcasts.releaseLimit, + modulesLoader.scope.config.transactions.poolStorageTxsLimit, + modulesLoader.scope.config.transactions.poolProcessInterval, + __trsLogic, + modulesLoader.scope.bus, + modulesLoader.scope.logger + ); modulesLoader.initModules([ {accounts: require('../../../../modules/accounts')}, @@ -185,7 +185,7 @@ describe('txPool', function () { }); it('should be ok when add transactions to fill pool storage', function (done) { - var trx = transactions.slice(1,transactions.length) + var trx = transactions.slice(1,transactions.length); txPool.add(trx, function (err, cbtx) { if (err) { done(err); @@ -280,7 +280,7 @@ describe('txPool', function () { }); }); - describe('broadcast transactions', function() { + describe('broadcast transactions', function () { var broadcastTx; it('should be ok when serialize transaction', function (done) { @@ -304,22 +304,22 @@ describe('txPool', function () { }); }); - describe('process worker', function() { + describe('process worker', function () { }); - describe('getters', function() { + describe('getters', function () { - describe('get transaction by id', function() { + describe('get transaction by id', function () { - xit('should be ok when transaction is in unverified list', function (done) { + it.skip('should be ok when transaction is in unverified list', function (done) { var transaction = txPool.get(transactions[5].id); expect(transaction.tx).to.deep.equal(transactions[5]); expect(transaction.status).to.equal('unverified'); done(); }); - xit('should be ok when transaction is in pending list', function (done) { + it.skip('should be ok when transaction is in pending list', function (done) { var transaction = txPool.get(transactions[5].id); expect(transaction.tx).to.deep.equal(transactions[5]); expect(transaction.status).to.equal('pending'); @@ -341,23 +341,23 @@ describe('txPool', function () { }); }); - describe('get all by pool list', function() { + describe('get all by pool list', function () { it('should be ok when pool list is unverified', function (done) { var txs = txPool.getByPoolList('unverified'); - expect(txs.length).to.equal(0) + expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is pending', function (done) { var txs = txPool.getByPoolList('pending'); - expect(txs.length).to.equal(0) + expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is ready', function (done) { var txs = txPool.getByPoolList('ready'); - expect(txs.length).to.equal(5) + expect(txs.length).to.equal(5); done(); }); @@ -368,7 +368,7 @@ describe('txPool', function () { }); }); - describe('get all by id (address)', function() { + describe('get all by id (address)', function () { it('should be ok when sender account is valid', function (done) { var txs = txPool.getByAccountId('2737453412992791987L', 'sender'); @@ -417,7 +417,7 @@ describe('txPool', function () { }); }); - describe('get all by publicKey', function() { + describe('get all by publicKey', function () { it('should be ok when sender publicKey is valid', function (done) { var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'sender'); From 24b3ed409cee48aaadddfd5f9fcbfadc693d47d8 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 15:07:11 +0200 Subject: [PATCH 06/86] Delete array queues, getAll as entry point --- logic/transactions/pool.js | 279 ++++++++------------------- test/unit/logic/transactions/pool.js | 61 +++--- 2 files changed, 108 insertions(+), 232 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index aa36e1190ba..ddaa5a61f30 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -24,7 +24,7 @@ var modules, library, self, __private = {}, pool = {}; * @param {Object} logger */ // Constructor -function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, transaction, bus, logger) { +function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, bus, logger) { library = { logger: logger, bus: bus, @@ -38,22 +38,23 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, trans }, transactions: { poolStorageTxsLimit: poolLimit, - poolProcessInterval: poolInterval + poolProcessInterval: poolInterval, + poolExpiryInterval: poolExpiryInterval } }, }; self = this; - self.processed = 0; self.poolStorageTxsLimit = library.config.transactions.poolStorageTxsLimit; self.poolProcessInterval = library.config.transactions.poolProcessInterval; - self.bundledInterval = library.config.broadcasts.broadcastInterval; + self.poolExpiryInterval = library.config.transactions.poolExpiryInterval; pool = { - unverified: { transactions: [], index: {} }, + unverified: { transactions: {}, count: 0 }, verified:{ - pending: { transactions: [], index: {} }, - ready: { transactions: [], index: {} } - } + pending: { transactions: {}, count: 0 }, + ready: { transactions: {}, count: 0 } + }, + invalid: { ids: {}, count: 0 } }; // Bundled transaction timer @@ -66,8 +67,19 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, trans }); } - jobsQueue.register('txPoolNextBundle', nextBundle, self.bundledInterval); + jobsQueue.register('txPoolNextBundle', nextBundle, self.poolProcessInterval); + // Transaction expiry timer + function nextExpiry (cb) { + self.expireTransactions(function (err) { + if (err) { + library.logger.log('Transaction expiry timer', err); + } + return setImmediate(cb); + }); + } + + jobsQueue.register('txPoolNextExpiry', nextExpiry, self.poolExpiryInterval); } // Public methods @@ -75,13 +87,11 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, trans * Bounds input parameters to private variable modules. * @param {Accounts} accounts * @param {Transactions} transactions - * @param {Loader} loader */ -TxPool.prototype.bind = function (accounts, transactions, loader) { +TxPool.prototype.bind = function (accounts, transactions) { modules = { accounts: accounts, transactions: transactions, - loader: loader, }; }; @@ -91,18 +101,9 @@ TxPool.prototype.bind = function (accounts, transactions, loader) { */ TxPool.prototype.getUsage = function () { return { - unverified: { - indexes: Object.keys(pool.unverified.index).length, - txs: pool.unverified.transactions.length - }, - pending: { - indexes: Object.keys(pool.verified.pending.index).length, - txs: pool.verified.pending.transactions.length - }, - ready: { - indexes: Object.keys(pool.verified.ready.index).length, - txs: pool.verified.ready.transactions.length - } + unverified: pool.unverified.count, + pending: pool.verified.pending.count, + ready: pool.verified.ready.count }; }; @@ -113,115 +114,76 @@ TxPool.prototype.getUsage = function () { * @return {Object} tx, status */ TxPool.prototype.get = function (id) { - var index = pool.unverified.index[id]; - if (index !== undefined) { + var tx = pool.unverified.transactions[id]; + if (tx !== undefined) { return { - tx: pool.unverified.transactions[index], + tx: tx, status: 'unverified' }; } - index = pool.verified.pending.index[id]; - if (index !== undefined) { + tx = pool.verified.pending.transactions[id]; + if (tx !== undefined) { return { - tx: pool.verified.pending.transactions[index], + tx: tx, status: 'pending' }; } - index = pool.verified.ready.index[id]; - if (index !== undefined) { + tx = pool.verified.ready.transactions[id]; + if (tx !== undefined) { return { - tx: pool.verified.ready.transactions[index], + tx: tx, status: 'ready' }; } return { tx: undefined, - status: 'Not in pool' + status: 'Transaction not in pool' }; }; /** - * Gets ready transactions ordered by fee and received time. - * @param {number} limit - * @return {transaction[]} - */ -TxPool.prototype.getReady = function (limit) { - var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'desc']); - if (limit && limit < r.length) { - r.splice(limit); - } - return r; -}; - -/** - * Gets transactions based on limit and pool list. + * Gets all transactions based on limited filters. * @implements {__private.getTxsFromPoolList} - * @param {string} poolList unverified, pending, ready - * @param {boolean} reverse - * @param {number} limit - * @return {[transactins]} transactions in pool list filter by limit. + * @param {string} filter + * @param {Object} params + * @return {[transaction]} transaction list based on filter. */ -TxPool.prototype.getByPoolList = function (poolList, reverse, limit) { - switch (poolList) { +TxPool.prototype.getAll = function (filter, params) { + switch (filter) { case 'unverified': - return __private.getTxsFromPoolList(pool.unverified.transactions, reverse, limit); + return __private.getTxsFromPoolList(pool.unverified.transactions, params.reverse, params.limit); case 'pending': - return __private.getTxsFromPoolList(pool.verified.pending.transactions, reverse, limit); + return __private.getTxsFromPoolList(pool.verified.pending.transactions, params.reverse, params.limit); case 'ready': - return __private.getTxsFromPoolList(pool.verified.ready.transactions, reverse, limit); + return __private.getTxsFromPoolList(pool.verified.ready.transactions, params.reverse, params.limit); + case 'sender_id': + return __private.getAllPoolTxsByFilter({'senderId': params.id}); + case 'sender_pk': + return __private.getAllPoolTxsByFilter({'senderPublicKey': params.publicKey}); + case 'recipient_id': + return __private.getAllPoolTxsByFilter({'recipientId': params.id}); + case 'recipient_pk': + return __private.getAllPoolTxsByFilter({'requesterPublicKey': params.publicKey}); default: - return 'Invalid pool list'; + return 'Invalid filter'; } }; /** - * Gets transactions from pool based on account address and entity: sender, recipient. - * @implements {__private.getAllPoolTxsByFilter} - * @param {account} id valid account address - * @param {string} entity sender, recipient - * @return {getTransactionList} Calls getTransactionList - */ -TxPool.prototype.getByAccountId = function (id, entity) { - var err = __private.checkAddress(id); - if (err) { - return err; - } - switch (entity) { - case 'sender': - return __private.getAllPoolTxsByFilter({'senderId': id}); - case 'recipient': - return __private.getAllPoolTxsByFilter({'recipientId': id}); - default: - return 'Invalid entity account address'; - } -}; - -/** - * Gets transactions from pool based on publicKey and entity: sender, recipient. - * @implements {__private.getAllPoolTxsByFilter} - * @param {string} publicKey - * @param {string} entity sender, requester - * @return {getTransactionList} Calls getTransactionList + * Gets ready transactions ordered by fee and received time. + * @param {number} limit + * @return {transaction[]} */ -TxPool.prototype.getByAccountPublicKey = function (publicKey, entity) { - var err = __private.checkPublicKey(publicKey); - if (err) { - return err; - } - switch (entity) { - case 'sender': - return __private.getAllPoolTxsByFilter({'senderPublicKey': publicKey}); - case 'requester': - return __private.getAllPoolTxsByFilter({'requesterPublicKey': publicKey}); - default: - return 'Invalid entity for public key'; +TxPool.prototype.getReady = function (limit) { + var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'desc']); + if (limit && limit < r.length) { + r.splice(limit); } + return r; }; - - /** * Checks sender has enough credit to apply transaction. * @param {transaction} transaction @@ -234,21 +196,6 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { return setImmediate(cb, balance); }; -/** - * Adds transactions to pool. - * @implements {__private.add} - * @param {transaction[]} transactions - * @param {function} cb - Callback function. - * @return {setImmediateCallback} err, transactions - */ -TxPool.prototype.receiveTransactions = function (transactions, cb) { - async.eachSeries(transactions, function (transaction, cb) { - __private.add(transaction, pool.unverified, cb); - }, function (err) { - return setImmediate(cb, err, transactions.length); - }); -}; - /** * Adds transactions to unverified pool list. * @implements {__private.add} @@ -270,6 +217,7 @@ TxPool.prototype.add = function (transactions, cb) { /** * Adds transactions to verified.ready pool list. * @implements {__private.addReady} + * @implements {delete} * @param {transaction} transaction * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb @@ -280,6 +228,7 @@ TxPool.prototype.addReady = function (transactions, cb) { } var resetReceivedAt = new Date(); async.eachSeries(transactions, function (transaction, eachSeriesCb) { + self.delete(transaction); transaction.receivedAt = resetReceivedAt; __private.addReady(transaction, pool.verified.ready, eachSeriesCb); }, function (err) { @@ -322,14 +271,6 @@ TxPool.prototype.delete = function (transaction) { */ TxPool.prototype.processPool = function (cb) { async.series({ - expireTransactions: function (seriesCb) { - __private.expireTransactions(function (err) { - if (err) { - library.logger.log('Transaction expiry timer', err); - } - return setImmediate(seriesCb); - }); - }, processUnverified: function (seriesCb) { async.eachSeries(pool.unverified.transactions, function (transaction, eachSeriesCb) { __private.delete(transaction.id, pool.unverified); @@ -364,12 +305,6 @@ TxPool.prototype.processPool = function (cb) { }, function (err) { return setImmediate(seriesCb, err); }); - }, - reindexQueues: function (seriesCb) { - if (self.processed > 1000) { - __private.reindexQueues(); - self.processed = 0; - } } }, function (err) { return setImmediate(cb, err); @@ -399,7 +334,7 @@ __private.getTxsFromPoolList = function (transactions, reverse, limit) { }; /** - * Gets transactions from pool list based on filter. + * Gets transactions from all pool lists based on filter. * @private * @param {Object} filter search criteria * @return {Objetc} transactions by pool list @@ -415,56 +350,20 @@ __private.getAllPoolTxsByFilter = function (filter) { }; /** - * Returns true if the id is present in at least one of the index values. - * Index values: unverified, verified.pending, verified.ready. + * Returns true if the id is present in at least one of the pool lists transactions. * @param {string} id * @return {boolean} */ __private.transactionInPool = function (id) { return [ - pool.unverified.index[id], - pool.verified.pending.index[id], - pool.verified.ready.index[id] + pool.unverified.transactions[id], + pool.verified.pending.transactions[id], + pool.verified.ready.transactions[id] ].filter(function (inList) { return inList !== undefined; }).length > 0; }; -/** - * Validates address. - * @param {string} address - * @return {null|err} - * @todo check address against mem_accounts - */ -__private.checkAddress = function (address) { - if (address.charAt(address.length-1) !== 'L') { - return 'Invalid address, last char must be "L"'; - } - if (address.slice(0,address.length-1).match(/^[0-9]+$/) === null) { - return 'Invalid address, must be numbers'; - } - return null; -}; - -/** - * Validates publicKey. - * @param {string} publicKey - * @return {null|err} - * @todo check publicKey against mem_accounts - */ -__private.checkPublicKey = function (publicKey) { - if (typeof publicKey !== 'string') { - return 'Invalid public key, must be a string'; - } - if (publicKey.length !== 64) { - return 'Invalid public key, must be 64 characters long'; - } - if (publicKey.match(/^[0-9A-Fa-f]+$/) === null) { - return 'Invalid public key, must be a hex string'; - } - return null; -}; - /** * Adds transactions to pool list. * Checks if tx is in pool. Checks pool limit. @@ -481,10 +380,8 @@ __private.add = function (transaction, poolList, cb) { if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); } else { - poolList.transactions.push(transaction); - var index = poolList.transactions.indexOf(transaction); - poolList.index[transaction.id] = index; - self.processed++; + poolList.transactions[transaction.id] = transaction; + poolList.count++; return setImmediate(cb); } }; @@ -492,18 +389,14 @@ __private.add = function (transaction, poolList, cb) { /** * Adds transactions to pool list. * Clear transaction if is in pool. - * @implements {__private.transactionInPool} * @param {transaction} transaction * @param {Object} poolList * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ __private.addReady = function (transaction, poolList, cb) { - self.delete(transaction); - poolList.transactions.push(transaction); - var index = poolList.transactions.indexOf(transaction); - poolList.index[transaction.id] = index; - self.processed++; + poolList.transactions[transaction.id] = transaction; + poolList.count++; return setImmediate(cb); }; @@ -514,24 +407,22 @@ __private.addReady = function (transaction, poolList, cb) { * @return {boolean} true if transaction id is on the list and was deleted */ __private.delete = function (id, poolList) { - var index = poolList.index[id]; + var index = poolList.transactions[id]; if (index !== undefined) { - poolList.transactions[index] = false; - delete poolList.index[id]; + delete poolList.transactions[id]; + poolList.count--; return true; } return false; }; /** - * Sums unverified, verified.pending and verified.ready indexes length. - * @return {Number} unverified, pending, ready + * Sums unverified, verified.pending and verified.ready counters. + * @return {Number} Total = unverified + pending + ready */ __private.countTxsPool = function () { - var totalPool = self.getUsage(); - - return totalPool.unverified.indexes + totalPool.pending.indexes + totalPool.ready.indexes; + return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; }; /** @@ -558,20 +449,6 @@ __private.expireTransactions = function (cb) { }); }; -/** - * Regenerates pool lists indexes and clears deleted transactions. - */ -__private.reindexQueues = function () { - [pool.unverified, pool.verified.pending, pool.verified.ready].forEach(function (list) { - list.index = {}; - list.transactions = list.transactions.filter(Boolean); - list.transactions.forEach(function (transaction) { - var index = list.transactions.indexOf(transaction); - list.index[transaction.id] = index; - }); - }); -}; - /** * Removes transactions if expired from pool list. * @private diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index f9db6bf66a9..c2557406c23 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -108,12 +108,14 @@ describe('txPool', function () { } modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; modulesLoader.scope.config.transactions.poolProcessInterval = 6000; + modulesLoader.scope.config.transactions.poolExpiryInterval = 30000; poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; txPool = new TxPool( modulesLoader.scope.config.broadcasts.broadcastInterval, modulesLoader.scope.config.broadcasts.releaseLimit, modulesLoader.scope.config.transactions.poolStorageTxsLimit, modulesLoader.scope.config.transactions.poolProcessInterval, + modulesLoader.scope.config.transactions.poolExpiryInterval, __trsLogic, modulesLoader.scope.bus, modulesLoader.scope.logger @@ -147,12 +149,9 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.unverified.indexes).to.be.a('number'); - expect(totals.pending.indexes).to.be.a('number'); - expect(totals.ready.indexes).to.be.a('number'); - expect(totals.unverified.txs).to.be.a('number'); - expect(totals.pending.txs).to.be.a('number'); - expect(totals.ready.txs).to.be.a('number'); + expect(totals.unverified).to.be.a('number'); + expect(totals.pending).to.be.a('number'); + expect(totals.ready).to.be.a('number'); poolTotals = totals; done(); }); @@ -171,8 +170,7 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.unverified.indexes).to.equal(poolTotals.unverified.indexes + 1); - expect(totals.unverified.txs).to.equal(poolTotals.unverified.txs + 1); + expect(totals.unverified).to.equal(poolTotals.unverified + 1); poolTotals = totals; done(); }); @@ -336,7 +334,7 @@ describe('txPool', function () { it('should fail when transaction is not in the pool', function (done) { var transaction = txPool.get(transactions[0].id); expect(transaction.tx).to.be.undefined; - expect(transaction.status).to.equal('Not in pool'); + expect(transaction.status).to.equal('Transaction not in pool'); done(); }); }); @@ -344,25 +342,25 @@ describe('txPool', function () { describe('get all by pool list', function () { it('should be ok when pool list is unverified', function (done) { - var txs = txPool.getByPoolList('unverified'); + var txs = txPool.getAll('unverified'); expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is pending', function (done) { - var txs = txPool.getByPoolList('pending'); + var txs = txPool.getAll('pending'); expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is ready', function (done) { - var txs = txPool.getByPoolList('ready'); + var txs = txPool.getAll('ready'); expect(txs.length).to.equal(5); done(); }); it('should fail when pool list is invalid', function (done) { - var txs = txPool.getByPoolList('unknown'); + var txs = txPool.getAll('unknown'); expect(txs).to.equal('Invalid pool list'); done(); }); @@ -371,7 +369,7 @@ describe('txPool', function () { describe('get all by id (address)', function () { it('should be ok when sender account is valid', function (done) { - var txs = txPool.getByAccountId('2737453412992791987L', 'sender'); + var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); @@ -380,21 +378,21 @@ describe('txPool', function () { }); it('should fail when sender account last char is not L', function (done) { - var txs = txPool.getByAccountId('2737453412992791987M', 'sender'); + var txs = txPool.getAll('sender_id', { id: '2737453412992791987M' }); expect(txs).to.equal('Invalid address, last char must be "L"'); done(); }); it('should fail when sender account main body is not a number', function (done) { - var txs = txPool.getByAccountId('A737453412992791987L', 'sender'); + var txs = txPool.getAll('sender_id', { id: 'A737453412992791987L' }); expect(txs).to.equal('Invalid address, must be numbers'); done(); }); it('should be ok when recipient account is valid', function (done) { - var txs = txPool.getByAccountId('16313739661670634666L', 'recipient'); + var txs = txPool.getAll('recipient_id', { id: '16313739661670634666L' }); expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); @@ -403,14 +401,14 @@ describe('txPool', function () { }); it('should fail when recipient account last char is not L', function (done) { - var txs = txPool.getByAccountId('16313739661670634666M', 'recipient'); + var txs = txPool.getAll('recipient_id', { id: '16313739661670634666M' }); expect(txs).to.equal('Invalid address, last char must be "L"'); done(); }); it('should fail when recipient account main body is not a number', function (done) { - var txs = txPool.getByAccountId('A6313739661670634666L', 'recipient'); + var txs = txPool.getAll('recipient_id', { id: 'A6313739661670634666L' }); expect(txs).to.equal('Invalid address, must be numbers'); done(); @@ -419,7 +417,7 @@ describe('txPool', function () { describe('get all by publicKey', function () { it('should be ok when sender publicKey is valid', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'sender'); + var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); @@ -428,34 +426,35 @@ describe('txPool', function () { }); it('should fail when sender publicKey is not a string', function (done) { - var txs = txPool.getByAccountPublicKey(123456789, 'sender'); + var txs = txPool.getAll('sender_pk', { publicKey: 123456789 }); expect(txs).to.equal('Invalid public key, must be a string'); done(); }); it('should fail when sender publicKey is less than 64 characters long', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7', 'sender'); + var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7' }); expect(txs).to.equal('Invalid public key, must be 64 characters long'); done(); }); - + it('should fail when sender publicKey is greater than 64 characters long', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1', 'sender'); + var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1' }); expect(txs).to.equal('Invalid public key, must be 64 characters long'); done(); }); it('should fail when sender publicKey is not hex string', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2c3po', 'sender'); + var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2c3po' }); expect(txs).to.equal('Invalid public key, must be a hex string'); done(); }); + it('should be ok when requester publicKey is valid', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'requester'); + var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); @@ -464,28 +463,28 @@ describe('txPool', function () { }); it('should fail when requester publicKey is not a string', function (done) { - var txs = txPool.getByAccountPublicKey(123456789, 'requester'); + var txs = txPool.getAll('recipient_pk', { publicKey: 123456789 }); expect(txs).to.equal('Invalid public key, must be a string'); done(); }); it('should fail when requester publicKey is less than 64 characters long', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7', 'requester'); + var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7' }); expect(txs).to.equal('Invalid public key, must be 64 characters long'); done(); }); - + it('should fail when requester publicKey is greater than 64 characters long', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1', 'requester'); + var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1' }); expect(txs).to.equal('Invalid public key, must be 64 characters long'); done(); }); it('should fail when requester publicKey is not hex string', function (done) { - var txs = txPool.getByAccountPublicKey('c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2r2d2', 'requester'); + var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2r2d2' }); expect(txs).to.equal('Invalid public key, must be a hex string'); done(); From 11793d621f66c694d04f02f6007a02b3bbde7538 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 16:15:41 +0200 Subject: [PATCH 07/86] Expire transactions worker --- logic/transactions/pool.js | 54 ++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index ddaa5a61f30..61db5da9a54 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -311,6 +311,30 @@ TxPool.prototype.processPool = function (cb) { }); }; +/** + * Expires transactions. + * @implements {__private.expireTxsFromList} + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | ids[] + */ +TxPool.prototype.expireTransactions = function (cb) { + var ids = []; + + async.waterfall([ + function (seriesCb) { + __private.expireTxsFromList(pool.unverified, ids, seriesCb); + }, + function (res, seriesCb) { + __private.expireTxsFromList(pool.verified.pending, ids, seriesCb); + }, + function (res, seriesCb) { + __private.expireTxsFromList(pool.verified.ready, ids, seriesCb); + } + ], function (err, ids) { + return setImmediate(cb, err, ids); + }); +}; + // Private /** * Gets reversed or limited transactions from input parameter. @@ -321,8 +345,10 @@ TxPool.prototype.processPool = function (cb) { * @return {transaction[]} */ __private.getTxsFromPoolList = function (transactions, reverse, limit) { - var txs = transactions.filter(Boolean); - + var txs; + if (reverse || limit){ + txs = Object.keys(transactions).reverse(); + } if (reverse) { txs = txs.reverse(); } @@ -425,30 +451,6 @@ __private.countTxsPool = function () { return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; }; -/** - * Expires transactions. - * @implements {__private.expireTxsFromList} - * @param {function} cb - Callback function. - * @return {setImmediateCallback} error | ids[] - */ -__private.expireTransactions = function (cb) { - var ids = []; - - async.waterfall([ - function (seriesCb) { - __private.expireTxsFromList(pool.unverified, ids, seriesCb); - }, - function (res, seriesCb) { - __private.expireTxsFromList(pool.verified.pending, ids, seriesCb); - }, - function (res, seriesCb) { - __private.expireTxsFromList(pool.verified.ready, ids, seriesCb); - } - ], function (err, ids) { - return setImmediate(cb, err, ids); - }); -}; - /** * Removes transactions if expired from pool list. * @private From 8176ca6c9f831bc81c29548dcc1b7395c019e556 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 16:16:24 +0200 Subject: [PATCH 08/86] Adjust getAll --- test/unit/logic/transactions/pool.js | 213 +++++++++------------------ 1 file changed, 66 insertions(+), 147 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index c2557406c23..93bf054b50c 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -108,7 +108,7 @@ describe('txPool', function () { } modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; modulesLoader.scope.config.transactions.poolProcessInterval = 6000; - modulesLoader.scope.config.transactions.poolExpiryInterval = 30000; + modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; txPool = new TxPool( modulesLoader.scope.config.broadcasts.broadcastInterval, @@ -195,7 +195,7 @@ describe('txPool', function () { it('should be ok when pool totals are equal to pool storage limit', function (done) { var totals = txPool.getUsage(); - var currentStorage = totals.unverified.indexes + totals.pending.indexes + totals.ready.indexes; + var currentStorage = totals.unverified + totals.pending + totals.ready; expect(totals).to.be.an('object'); expect(currentStorage).to.equal(poolStorageTxsLimit); poolTotals = totals; @@ -225,8 +225,7 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.unverified.indexes).to.equal(poolTotals.unverified.indexes - 1); - expect(totals.unverified.txs).to.equal(poolTotals.unverified.txs); + expect(totals.unverified).to.equal(poolTotals.unverified - 1); poolTotals = totals; done(); }); @@ -242,8 +241,7 @@ describe('txPool', function () { done(err); } expect(cbtx).to.be.undefined; - poolTotals.ready.indexes += transactions.length; - poolTotals.ready.txs += transactions.length; + poolTotals.ready += transactions.length; done(); }); }); @@ -269,8 +267,7 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.ready.indexes).to.equal(poolTotals.ready.indexes - 1); - expect(totals.ready.txs).to.equal(poolTotals.ready.txs); + expect(totals.ready).to.equal(poolTotals.ready - 1); poolTotals = totals; done(); @@ -339,156 +336,78 @@ describe('txPool', function () { }); }); - describe('get all by pool list', function () { + describe('getAll', function () { - it('should be ok when pool list is unverified', function (done) { - var txs = txPool.getAll('unverified'); - expect(txs.length).to.equal(0); - done(); - }); - - it('should be ok when pool list is pending', function (done) { - var txs = txPool.getAll('pending'); - expect(txs.length).to.equal(0); - done(); - }); - - it('should be ok when pool list is ready', function (done) { - var txs = txPool.getAll('ready'); - expect(txs.length).to.equal(5); - done(); - }); - - it('should fail when pool list is invalid', function (done) { - var txs = txPool.getAll('unknown'); - expect(txs).to.equal('Invalid pool list'); - done(); - }); - }); - - describe('get all by id (address)', function () { + describe('by pool list', function () { - it('should be ok when sender account is valid', function (done) { - var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); - done(); - }); - - it('should fail when sender account last char is not L', function (done) { - var txs = txPool.getAll('sender_id', { id: '2737453412992791987M' }); - - expect(txs).to.equal('Invalid address, last char must be "L"'); - done(); - }); - - it('should fail when sender account main body is not a number', function (done) { - var txs = txPool.getAll('sender_id', { id: 'A737453412992791987L' }); - - expect(txs).to.equal('Invalid address, must be numbers'); - done(); - }); + it('should be ok when pool list is unverified', function (done) { + var txs = txPool.getAll('unverified', { reverse: true, limit: null}); + expect(txs.length).to.equal(0); + done(); + }); - it('should be ok when recipient account is valid', function (done) { - var txs = txPool.getAll('recipient_id', { id: '16313739661670634666L' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); - done(); - }); - - it('should fail when recipient account last char is not L', function (done) { - var txs = txPool.getAll('recipient_id', { id: '16313739661670634666M' }); - - expect(txs).to.equal('Invalid address, last char must be "L"'); - done(); + it('should be ok when pool list is pending', function (done) { + var txs = txPool.getAll('pending', { reverse: true, limit: null}); + expect(txs.length).to.equal(0); + done(); + }); + + it('should be ok when pool list is ready', function (done) { + var txs = txPool.getAll('ready', { reverse: true, limit: null}); + expect(txs.length).to.equal(5); + done(); + }); + + it('should fail when filter is invalid', function (done) { + var txs = txPool.getAll('unknown', { reverse: true, limit: null}); + expect(txs).to.equal('Invalid filter'); + done(); + }); }); - it('should fail when recipient account main body is not a number', function (done) { - var txs = txPool.getAll('recipient_id', { id: 'A6313739661670634666L' }); + describe('by id (address) and publicKey', function () { + + it('should be ok when sender account is valid', function (done) { + var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should be ok when recipient account is valid', function (done) { + var txs = txPool.getAll('recipient_id', { id: '16313739661670634666L' }); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); - expect(txs).to.equal('Invalid address, must be numbers'); - done(); + it('should be ok when sender publicKey is valid', function (done) { + var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should be ok when requester publicKey is valid', function (done) { + var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); + + expect(txs.unverified.length).to.equal(0); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); }); }); - describe('get all by publicKey', function () { - it('should be ok when sender publicKey is valid', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); - done(); - }); - - it('should fail when sender publicKey is not a string', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 123456789 }); - - expect(txs).to.equal('Invalid public key, must be a string'); - done(); - }); - - it('should fail when sender publicKey is less than 64 characters long', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7' }); - - expect(txs).to.equal('Invalid public key, must be 64 characters long'); - done(); - }); - - it('should fail when sender publicKey is greater than 64 characters long', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1' }); - - expect(txs).to.equal('Invalid public key, must be 64 characters long'); - done(); - }); - it('should fail when sender publicKey is not hex string', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2c3po' }); + describe('next', function () { - expect(txs).to.equal('Invalid public key, must be a hex string'); - done(); - }); - - it('should be ok when requester publicKey is valid', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); - done(); - }); - - it('should fail when requester publicKey is not a string', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 123456789 }); - - expect(txs).to.equal('Invalid public key, must be a string'); - done(); - }); - - it('should fail when requester publicKey is less than 64 characters long', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7' }); - - expect(txs).to.equal('Invalid public key, must be 64 characters long'); - done(); - }); - - it('should fail when requester publicKey is greater than 64 characters long', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5c1' }); - - expect(txs).to.equal('Invalid public key, must be 64 characters long'); - done(); - }); - - it('should fail when requester publicKey is not hex string', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2r2d2' }); - - expect(txs).to.equal('Invalid public key, must be a hex string'); - done(); - }); }); }); }); \ No newline at end of file From 6c7fbea5eff405f5395ae85e71ba9b8e5966af60 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 16:24:56 +0200 Subject: [PATCH 09/86] Move private functions above public --- logic/transactions/pool.js | 491 +++++++++++++++++++------------------ 1 file changed, 246 insertions(+), 245 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 61db5da9a54..6daff9583e5 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -82,6 +82,252 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE jobsQueue.register('txPoolNextExpiry', nextExpiry, self.poolExpiryInterval); } + +// Private +/** + * Gets reversed or limited transactions from input parameter. + * @private + * @param {transaction[]} transactions + * @param {boolean} reverse + * @param {number} limit + * @return {transaction[]} + */ +__private.getTxsFromPoolList = function (transactions, reverse, limit) { + var txs; + if (reverse || limit){ + txs = Object.keys(transactions).reverse(); + } + if (reverse) { + txs = txs.reverse(); + } + if (limit) { + txs.splice(limit); + } + + return txs; +}; + +/** + * Gets transactions from all pool lists based on filter. + * @private + * @param {Object} filter search criteria + * @return {Objetc} transactions by pool list + */ +__private.getAllPoolTxsByFilter = function (filter) { + var txs = { + unverified: _.filter(pool.unverified, filter), + pending: _.filter(pool.verified.pending, filter), + ready: _.filter(pool.verified.ready, filter) + }; + + return txs; +}; + +/** + * Returns true if the id is present in at least one of the pool lists transactions. + * @param {string} id + * @return {boolean} + */ +__private.transactionInPool = function (id) { + return [ + pool.unverified.transactions[id], + pool.verified.pending.transactions[id], + pool.verified.ready.transactions[id] + ].filter(function (inList) { + return inList !== undefined; + }).length > 0; +}; + +/** + * Adds transactions to pool list. + * Checks if tx is in pool. Checks pool limit. + * @implements {__private.transactionInPool} + * @param {transaction} transaction + * @param {Object} poolList + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.add = function (transaction, poolList, cb) { + if (__private.countTxsPool() >= self.poolStorageTxsLimit) { + return setImmediate(cb, 'Transaction pool is full'); + } + if (__private.transactionInPool(transaction.id)) { + return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); + } else { + poolList.transactions[transaction.id] = transaction; + poolList.count++; + return setImmediate(cb); + } +}; + +/** + * Adds transactions to pool list. + * Clear transaction if is in pool. + * @param {transaction} transaction + * @param {Object} poolList + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.addReady = function (transaction, poolList, cb) { + poolList.transactions[transaction.id] = transaction; + poolList.count++; + return setImmediate(cb); +}; + +/** + * Deletes id from pool list index. + * @param {string} id + * @param {Object} poolList + * @return {boolean} true if transaction id is on the list and was deleted + */ +__private.delete = function (id, poolList) { + var index = poolList.transactions[id]; + + if (index !== undefined) { + delete poolList.transactions[id]; + poolList.count--; + return true; + } + return false; +}; + +/** + * Sums unverified, verified.pending and verified.ready counters. + * @return {Number} Total = unverified + pending + ready + */ +__private.countTxsPool = function () { + return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; +}; + +/** + * Removes transactions if expired from pool list. + * @private + * @implements {__private.transactionTimeOut} + * @implements {__private.delete} + * @param {Object[]} poolList + * @param {string[]} parentIds + * @param {function} cb - Callback function + * @return {setImmediateCallback} error | ids[] + */ +__private.expireTxsFromList = function (poolList, parentIds, cb) { + var ids = []; + + async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { + if (!transaction) { + return setImmediate(eachSeriesCb); + } + + var timeNow = Math.floor(Date.now() / 1000); + var timeOut = __private.transactionTimeOut(transaction); + // transaction.receivedAt is instance of Date + console.log('expireTransactions - transaction.receivedAt',transaction.receivedAt); + var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); + + if (seconds > timeOut) { + ids.push(transaction.id); + __private.delete(poolList, transaction.id); + library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); + return setImmediate(eachSeriesCb); + } else { + return setImmediate(eachSeriesCb); + } + }, function (err) { + return setImmediate(cb, err, ids.concat(parentIds)); + }); +}; + +/** + * Calculates timeout based on transaction. + * @private + * @param {transaction} transaction + * @return {number} timeOut + */ +__private.transactionTimeOut = function (transaction) { + if (transaction.type === transactionTypes.MULTI) { + return (transaction.asset.multisignature.lifetime * 3600); + } else if (Array.isArray(transaction.signatures)) { + return (constants.unconfirmedTransactionTimeOut * 8); + } else { + return (constants.unconfirmedTransactionTimeOut); + } +}; + +/** + * Gets sender account, verifies multisignatures, gets requester, + * process transaction and verifies. + * @private + * @implements {accounts.setAccountAndGet} + * @implements {accounts.getAccount} + * @implements {logic.transaction.process} + * @implements {logic.transaction.verify} + * @param {transaction} transaction + * @param {object} broadcast + * @param {function} cb - Callback function + * @returns {setImmediateCallback} errors | sender + */ +__private.processUnverifiedTransaction = function (transaction, broadcast, cb) { + if (!transaction) { + return setImmediate(cb, 'Missing transaction'); + } + + async.waterfall([ + function setAccountAndGet (waterCb) { + modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); + }, + function getRequester (sender, waterCb) { + var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; + + if (multisignatures) { + transaction.signatures = transaction.signatures || []; + } + + if (sender && transaction.requesterPublicKey && multisignatures) { + modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { + if (!requester) { + return setImmediate(waterCb, 'Requester not found'); + } else { + return setImmediate(waterCb, null, sender, requester); + } + }); + } else { + return setImmediate(waterCb, null, sender, null); + } + }, + function processTransaction (sender, requester, waterCb) { + library.logic.transaction.process(transaction, sender, requester, function (err) { + if (err) { + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, sender); + } + }); + }, + function normalizeTransaction (sender, waterCb) { + try { + transaction = library.logic.transaction.objectNormalize(transaction); + return setImmediate(waterCb, null, sender); + } catch (err) { + return setImmediate(waterCb, err); + } + }, + function verifyTransaction (sender, waterCb) { + library.logic.transaction.verify(transaction, sender, function (err) { + if (err) { + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, sender); + } + }); + } + ], function (err, sender) { + if (!err) { + library.bus.message('unconfirmedTransaction', transaction, broadcast); + } + + return setImmediate(cb, err, sender); + }); +}; + // Public methods /** * Bounds input parameters to private variable modules. @@ -335,250 +581,5 @@ TxPool.prototype.expireTransactions = function (cb) { }); }; -// Private -/** - * Gets reversed or limited transactions from input parameter. - * @private - * @param {transaction[]} transactions - * @param {boolean} reverse - * @param {number} limit - * @return {transaction[]} - */ -__private.getTxsFromPoolList = function (transactions, reverse, limit) { - var txs; - if (reverse || limit){ - txs = Object.keys(transactions).reverse(); - } - if (reverse) { - txs = txs.reverse(); - } - if (limit) { - txs.splice(limit); - } - - return txs; -}; - -/** - * Gets transactions from all pool lists based on filter. - * @private - * @param {Object} filter search criteria - * @return {Objetc} transactions by pool list - */ -__private.getAllPoolTxsByFilter = function (filter) { - var txs = { - unverified: _.filter(pool.unverified, filter), - pending: _.filter(pool.verified.pending, filter), - ready: _.filter(pool.verified.ready, filter) - }; - - return txs; -}; - -/** - * Returns true if the id is present in at least one of the pool lists transactions. - * @param {string} id - * @return {boolean} - */ -__private.transactionInPool = function (id) { - return [ - pool.unverified.transactions[id], - pool.verified.pending.transactions[id], - pool.verified.ready.transactions[id] - ].filter(function (inList) { - return inList !== undefined; - }).length > 0; -}; - -/** - * Adds transactions to pool list. - * Checks if tx is in pool. Checks pool limit. - * @implements {__private.transactionInPool} - * @param {transaction} transaction - * @param {Object} poolList - * @param {function} cb - Callback function. - * @return {setImmediateCallback} error | cb - */ -__private.add = function (transaction, poolList, cb) { - if (__private.countTxsPool() >= self.poolStorageTxsLimit) { - return setImmediate(cb, 'Transaction pool is full'); - } - if (__private.transactionInPool(transaction.id)) { - return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); - } else { - poolList.transactions[transaction.id] = transaction; - poolList.count++; - return setImmediate(cb); - } -}; - -/** - * Adds transactions to pool list. - * Clear transaction if is in pool. - * @param {transaction} transaction - * @param {Object} poolList - * @param {function} cb - Callback function. - * @return {setImmediateCallback} error | cb - */ -__private.addReady = function (transaction, poolList, cb) { - poolList.transactions[transaction.id] = transaction; - poolList.count++; - return setImmediate(cb); -}; - -/** - * Deletes id from pool list index. - * @param {string} id - * @param {Object} poolList - * @return {boolean} true if transaction id is on the list and was deleted - */ -__private.delete = function (id, poolList) { - var index = poolList.transactions[id]; - - if (index !== undefined) { - delete poolList.transactions[id]; - poolList.count--; - return true; - } - return false; -}; - -/** - * Sums unverified, verified.pending and verified.ready counters. - * @return {Number} Total = unverified + pending + ready - */ -__private.countTxsPool = function () { - return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; -}; - -/** - * Removes transactions if expired from pool list. - * @private - * @implements {__private.transactionTimeOut} - * @implements {__private.delete} - * @param {Object[]} poolList - * @param {string[]} parentIds - * @param {function} cb - Callback function - * @return {setImmediateCallback} error | ids[] - */ -__private.expireTxsFromList = function (poolList, parentIds, cb) { - var ids = []; - - async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { - if (!transaction) { - return setImmediate(eachSeriesCb); - } - - var timeNow = Math.floor(Date.now() / 1000); - var timeOut = __private.transactionTimeOut(transaction); - // transaction.receivedAt is instance of Date - console.log('expireTransactions - transaction.receivedAt',transaction.receivedAt); - var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); - - if (seconds > timeOut) { - ids.push(transaction.id); - __private.delete(poolList, transaction.id); - library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); - return setImmediate(eachSeriesCb); - } else { - return setImmediate(eachSeriesCb); - } - }, function (err) { - return setImmediate(cb, err, ids.concat(parentIds)); - }); -}; - -/** - * Calculates timeout based on transaction. - * @private - * @param {transaction} transaction - * @return {number} timeOut - */ -__private.transactionTimeOut = function (transaction) { - if (transaction.type === transactionTypes.MULTI) { - return (transaction.asset.multisignature.lifetime * 3600); - } else if (Array.isArray(transaction.signatures)) { - return (constants.unconfirmedTransactionTimeOut * 8); - } else { - return (constants.unconfirmedTransactionTimeOut); - } -}; - -/** - * Gets sender account, verifies multisignatures, gets requester, - * process transaction and verifies. - * @private - * @implements {accounts.setAccountAndGet} - * @implements {accounts.getAccount} - * @implements {logic.transaction.process} - * @implements {logic.transaction.verify} - * @param {transaction} transaction - * @param {object} broadcast - * @param {function} cb - Callback function - * @returns {setImmediateCallback} errors | sender - */ -__private.processUnverifiedTransaction = function (transaction, broadcast, cb) { - if (!transaction) { - return setImmediate(cb, 'Missing transaction'); - } - - async.waterfall([ - function setAccountAndGet (waterCb) { - modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); - }, - function getRequester (sender, waterCb) { - var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; - - if (multisignatures) { - transaction.signatures = transaction.signatures || []; - } - - if (sender && transaction.requesterPublicKey && multisignatures) { - modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { - if (!requester) { - return setImmediate(waterCb, 'Requester not found'); - } else { - return setImmediate(waterCb, null, sender, requester); - } - }); - } else { - return setImmediate(waterCb, null, sender, null); - } - }, - function processTransaction (sender, requester, waterCb) { - library.logic.transaction.process(transaction, sender, requester, function (err) { - if (err) { - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, sender); - } - }); - }, - function normalizeTransaction (sender, waterCb) { - try { - transaction = library.logic.transaction.objectNormalize(transaction); - return setImmediate(waterCb, null, sender); - } catch (err) { - return setImmediate(waterCb, err); - } - }, - function verifyTransaction (sender, waterCb) { - library.logic.transaction.verify(transaction, sender, function (err) { - if (err) { - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, sender); - } - }); - } - ], function (err, sender) { - if (!err) { - library.bus.message('unconfirmedTransaction', transaction, broadcast); - } - - return setImmediate(cb, err, sender); - }); -}; - // Export module.exports = TxPool; \ No newline at end of file From 13bd0d8e39b62bf1cb193a7b7da11f9373506963 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 19:26:13 +0200 Subject: [PATCH 10/86] Improve addReady, getReady test --- test/unit/logic/transactions/pool.js | 30 +++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 93bf054b50c..a59b223699c 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -229,6 +229,13 @@ describe('txPool', function () { poolTotals = totals; done(); }); + + it('should fail when delete transaction that is not in pool', function (done) { + var deleteTx = txPool.delete(transactions[0]); + + expect(deleteTx).to.be.an('array').that.is.empty; + done(); + }); }); }); @@ -251,6 +258,28 @@ describe('txPool', function () { expect(readyTxs[0].fee).to.be.at.least(readyTxs[1].fee); expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); + expect(readyTxs[3].fee).to.be.at.least(readyTxs[4].fee); + expect(readyTxs[4].fee).to.be.at.least(readyTxs[5].fee); + done(); + }); + + it('should be ok when add transaction[1] again to ready', function (done) { + txPool.addReady(transactions[1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when get transactions from ready', function (done) { + var readyTxs = txPool.getReady(); + expect(readyTxs[0].receivedAt).to.not.equal(readyTxs[1].receivedAt); + expect(readyTxs[1].receivedAt).to.equal(readyTxs[2].receivedAt); + expect(readyTxs[2].receivedAt).to.equal(readyTxs[3].receivedAt); + expect(readyTxs[3].receivedAt).to.equal(readyTxs[4].receivedAt); + expect(readyTxs[4].receivedAt).to.equal(readyTxs[5].receivedAt); done(); }); @@ -270,7 +299,6 @@ describe('txPool', function () { expect(totals.ready).to.equal(poolTotals.ready - 1); poolTotals = totals; done(); - }); }); }); From 01af273d89c616b1a35af7fb0e5aded2e1bfeb9c Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 13 Sep 2017 19:39:28 +0200 Subject: [PATCH 11/86] Adjust getAll by address and public key --- logic/transactions/pool.js | 6 +++--- test/unit/logic/transactions/pool.js | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 6daff9583e5..cb68de47cc8 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -115,9 +115,9 @@ __private.getTxsFromPoolList = function (transactions, reverse, limit) { */ __private.getAllPoolTxsByFilter = function (filter) { var txs = { - unverified: _.filter(pool.unverified, filter), - pending: _.filter(pool.verified.pending, filter), - ready: _.filter(pool.verified.ready, filter) + unverified: _.filter(pool.unverified.transactions, filter), + pending: _.filter(pool.verified.pending.transactions, filter), + ready: _.filter(pool.verified.ready.transactions, filter) }; return txs; diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index a59b223699c..2929d1adeb4 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -400,7 +400,7 @@ describe('txPool', function () { expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); + expect(txs.ready.length).to.equal(3); done(); }); @@ -409,7 +409,7 @@ describe('txPool', function () { expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); + expect(txs.ready.length).to.equal(1); done(); }); @@ -418,7 +418,7 @@ describe('txPool', function () { expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); + expect(txs.ready.length).to.equal(3); done(); }); @@ -433,7 +433,6 @@ describe('txPool', function () { }); }); - describe('next', function () { }); From 8eb1dab86bdbe06bc47b474c76975424a0927b18 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Sat, 16 Sep 2017 17:44:47 +0200 Subject: [PATCH 12/86] check balance --- logic/transactions/pool.js | 60 +++++- test/unit/logic/transactions/pool.js | 281 ++++++++++++++++++++------- 2 files changed, 267 insertions(+), 74 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index cb68de47cc8..e61594c067a 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -6,6 +6,7 @@ var config = require('../../config.json'); var constants = require('../../helpers/constants.js'); var jobsQueue = require('../../helpers/jobsQueue.js'); var transactionTypes = require('../../helpers/transactionTypes.js'); +var bignum = require('../../helpers/bignum.js'); // Private fields var modules, library, self, __private = {}, pool = {}; @@ -24,12 +25,13 @@ var modules, library, self, __private = {}, pool = {}; * @param {Object} logger */ // Constructor -function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, bus, logger) { +function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger) { library = { logger: logger, bus: bus, logic: { transaction: transaction, + account, account }, config: { broadcasts: { @@ -392,6 +394,7 @@ TxPool.prototype.get = function (id) { /** * Gets all transactions based on limited filters. * @implements {__private.getTxsFromPoolList} + * @implements {__private.getAllPoolTxsByFilter} * @param {string} filter * @param {Object} params * @return {[transaction]} transaction list based on filter. @@ -420,7 +423,7 @@ TxPool.prototype.getAll = function (filter, params) { /** * Gets ready transactions ordered by fee and received time. * @param {number} limit - * @return {transaction[]} + * @return {[transaction]} */ TxPool.prototype.getReady = function (limit) { var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'desc']); @@ -438,8 +441,57 @@ TxPool.prototype.getReady = function (limit) { * @return {setImmediateCallback} err, transactions */ TxPool.prototype.checkBalance = function (transaction, sender, cb) { - var balance; - return setImmediate(cb, balance); + var poolBalance = new bignum('0'), paymentTxs, receiptTxs; + + library.logic.account.get({ address: sender }, 'balance', function (err, account) { + if (err) { + return setImmediate(cb, err); + } + + // total payments + paymentTxs = self.getAll('sender_id', { id: sender }); + ['unverified','pending','ready'].forEach(function (paymentTxList) { + if (paymentTxs[paymentTxList].length > 0) { + paymentTxs[paymentTxList].forEach(function (paymentTx) { + if (paymentTx.amount) { + poolBalance = poolBalance.minus(paymentTx.amount.toString()); + } + poolBalance = poolBalance.minus(paymentTx.fee.toString()); + }); + } + }); + + // total receipts + receiptTxs = self.getAll('recipient_id', { id: sender }); + ['unverified','pending','ready'].forEach(function (receiptTxList) { + if (receiptTxs[receiptTxList].length > 0) { + receiptTxs[receiptTxList].forEach(function (receiptTx) { + if (receiptTx.type === transactionTypes.SEND) { + poolBalance = poolBalance.plus(paymentTx.amount.toString()); + } + }); + } + }); + + // total balance + var balance = new bignum(account.balance.toString()); + balance = balance.plus(poolBalance); + + // Check confirmed sender balance + var amount = new bignum(transaction.amount.toString()).plus(transaction.fee.toString()); + var exceeded = balance.lessThan(amount); + + if (exceeded) { + return setImmediate(cb, [ + 'Account does not have enough LSK:', sender, + 'balance:', balance.div(Math.pow(10,8)) + ].join(' ')); + } + + return setImmediate(cb, null, [ + 'balance:', balance.div(Math.pow(10,8)) + ].join(' ')); + }); }; /** diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 2929d1adeb4..5a7d4df4722 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -5,94 +5,167 @@ var expect = require('chai').expect; var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); +var Account = require('../../../../logic/account.js'); var bson = require('../../../../helpers/bson.js'); var transactions = [ /* type: 0 - Transmit funds */ { 'type': 0, - 'amount': 100000000, + 'amount': 300000000, 'fee': 10000000, 'timestamp': 37943880, - 'recipientId': '16313739661670634666L', + 'recipientId': '2896019180726908125L', 'senderId': '2737453412992791987L', 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7249285091378090017' + 'id': '1' }, /* type: 1 - Register a second signature */ { 'type': 1, 'amount': 0, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'timestamp': 37943881, - 'recipientId': null, - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7249285091378090018', 'fee': 500000000, - 'senderId': '2737453412992791987L', 'asset': { 'signature': { - 'publicKey': 'The public key associated with the second passphrase' + 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' } - } + }, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'senderId': '2737453412992791987L', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '2' }, /* type: 2 - Register a delegate */ { 'type': 2, 'amount': 0, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'timestamp': 37943882, - 'recipientId': null, - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7249285091378090019', - 'fee': 500000000, - 'senderId': '2737453412992791987L', + 'fee': 2500000000, 'asset': { 'delegate': { - 'username': 'The chosen username', - 'publicKey': 'The public key associated with the second passphrase' + 'username': 'test_delegate_1', + 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' } - } + }, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'senderId': '2737453412992791987L', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '3' }, /* type: 3 - Submit votes */ { 'type': 3, - 'amount': 30000, - 'fee': 3, - 'id': '7249285091378090020' + 'amount': 0, + 'timestamp': 37943883, + 'fee': 100000000, + 'asset': { + 'votes': [] + }, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'senderId': '2737453412992791987L', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '4' }, /* type: 4 - Multisignature registration */ { - 'type': 4, - 'amount': 40000, - 'fee': 4, - 'id': '7249285091378090021' + 'type': 4, + 'timestamp': 37943884, + 'fee': 1000000000, + 'asset': { + 'multisignature': { + 'min': 2, + 'lifetime': 24, + 'keysgroup': [ + "+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb", + "+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5" + ] + } + }, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'senderId': '2737453412992791987L', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '5' }, - /* type: 0 - Transmit funds Account does not have enough LSK*/ + /* type: 0 - Transmit funds */ { 'type': 0, - 'amount': 10000000000000000, + 'amount': 300000000, 'fee': 10000000, - 'timestamp': 37943840, - 'recipientId': '16313739661670634666L', + 'timestamp': 37943886, + 'recipientId': '2896019180726908125L', 'senderId': '2737453412992791987L', 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7249285091378090022' + 'id': '6' }, + /* type: 0 - Transmit funds Account does not have enough LSK*/ + { + 'type': 0, + 'amount': 800000000, + 'fee': 10000000, + 'timestamp': 37943885, + 'recipientId': '2737453412992791987L', + 'senderId': '2896019180726908125L', + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '7' + } ]; + var extraTransaction = { 'type': 0, - 'amount': 100000000, + 'amount': 400000000, 'fee': 10000000, - 'timestamp': 37943880, - 'recipientId': '16313739661670634666L', - 'senderId': '2737453412992791987L', + 'timestamp': 37943890, + 'recipientId': '2896019180726908125L', + 'senderId': '13898484363564790288L', 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7249285091378090023' + 'id': '8' }; + +var testAccounts = [ + { + account: { + username: 'test_1', + isDelegate: 1, + address: '2737453412992791987L', + publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + balance: 5300000000000000, + }, + secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', + },{ + account: { + username: 'test_2', + isDelegate: 0, + address: '2896019180726908125L', + publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + balance: 0, + }, + secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', + },{ + account: { + username: 'test_3', + isDelegate: 0, + address: '15240249857307028085L', + publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + balance: 3500000000000000, + }, + secret: 'song gather until exercise explain utility walk choice garbage cross route develop', + },{ + account: { + username: 'test_4', + isDelegate: 0, + address: '13898484363564790288L', + publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + balance: 3500000000000000, + }, + secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', + } +]; + describe('txPool', function () { var accounts; @@ -102,40 +175,92 @@ describe('txPool', function () { var poolStorageTxsLimit; before(function (done) { - modulesLoader.initLogic(Transaction, modulesLoader.scope, function (err, __trsLogic) { + + modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; + modulesLoader.scope.config.transactions.poolProcessInterval = 6000; + modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; + + modulesLoader.initLogicWithDb(Account, function (err, __accountLogic) { if (err) { return done(err); } - modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; - modulesLoader.scope.config.transactions.poolProcessInterval = 6000; - modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; - poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; - txPool = new TxPool( - modulesLoader.scope.config.broadcasts.broadcastInterval, - modulesLoader.scope.config.broadcasts.releaseLimit, - modulesLoader.scope.config.transactions.poolStorageTxsLimit, - modulesLoader.scope.config.transactions.poolProcessInterval, - modulesLoader.scope.config.transactions.poolExpiryInterval, - __trsLogic, - modulesLoader.scope.bus, - modulesLoader.scope.logger - ); - - modulesLoader.initModules([ - {accounts: require('../../../../modules/accounts')}, - ], [ - {'transaction': require('../../../../logic/transaction')}, - {'account': require('../../../../logic/account')} - ], {}, function (err, __modules) { + modulesLoader.initLogic(Transaction, modulesLoader.scope, function (err, __trsLogic) { if (err) { return done(err); } - txPool.bind( - __modules.accounts, - null, - __modules.loader + poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; + txPool = new TxPool( + modulesLoader.scope.config.broadcasts.broadcastInterval, + modulesLoader.scope.config.broadcasts.releaseLimit, + modulesLoader.scope.config.transactions.poolStorageTxsLimit, + modulesLoader.scope.config.transactions.poolProcessInterval, + modulesLoader.scope.config.transactions.poolExpiryInterval, + __trsLogic, + __accountLogic, + modulesLoader.scope.bus, + modulesLoader.scope.logger ); + + modulesLoader.initModules([ + {accounts: require('../../../../modules/accounts')}, + ], [ + {'transaction': require('../../../../logic/transaction')}, + {'account': require('../../../../logic/account')} + ], {}, function (err, __modules) { + if (err) { + return done(err); + } + txPool.bind( + __modules.accounts, + null, + __modules.loader + ); + __modules.accounts.onBind(__modules); + accounts = __modules.accounts; + done(); + }); + }); + }, modulesLoader.scope); + }); + + describe('setup database', function () { + + it('should be ok when generate account 1', function (done) { + accounts.setAccountAndGet(testAccounts[0].account, function (err, newaccount) { + if (err) { + return done(err); + } + expect(newaccount.address).to.equal(testAccounts[0].account.address); + done(); + }); + }); + + it('should be ok when generate account 2', function (done) { + accounts.setAccountAndGet(testAccounts[1].account, function (err, newaccount) { + if (err) { + return done(err); + } + expect(newaccount.address).to.equal(testAccounts[1].account.address); + done(); + }); + }); + it('should be ok when generate account 3', function (done) { + accounts.setAccountAndGet(testAccounts[2].account, function (err, newaccount) { + if (err) { + return done(err); + } + expect(newaccount.address).to.equal(testAccounts[2].account.address); + done(); + }); + }); + + it('should be ok when generate account 4', function (done) { + accounts.setAccountAndGet(testAccounts[3].account, function (err, newaccount) { + if (err) { + return done(err); + } + expect(newaccount.address).to.equal(testAccounts[3].account.address); done(); }); }); @@ -177,13 +302,13 @@ describe('txPool', function () { it('should fail when add same transaction type 0 to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { - expect(err).to.equal('Transaction is already in pool: 7249285091378090017'); + expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); done(); }); }); it('should be ok when add transactions to fill pool storage', function (done) { - var trx = transactions.slice(1,transactions.length); + var trx = transactions.slice(1,transactions.length-1); txPool.add(trx, function (err, cbtx) { if (err) { done(err); @@ -243,12 +368,12 @@ describe('txPool', function () { describe('method addReady/getReady', function () { it('should be ok when add transactions to ready', function (done) { - txPool.addReady(transactions, function (err, cbtx) { + txPool.addReady(transactions.slice(0,5), function (err, cbtx) { if (err) { done(err); } expect(cbtx).to.be.undefined; - poolTotals.ready += transactions.length; + poolTotals.ready += transactions.slice(0,5).length; done(); }); }); @@ -259,12 +384,11 @@ describe('txPool', function () { expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); expect(readyTxs[3].fee).to.be.at.least(readyTxs[4].fee); - expect(readyTxs[4].fee).to.be.at.least(readyTxs[5].fee); done(); }); - it('should be ok when add transaction[1] again to ready', function (done) { - txPool.addReady(transactions[1], function (err, cbtx) { + it('should be ok when add type 2 transaction again to ready', function (done) { + txPool.addReady(transactions[2], function (err, cbtx) { if (err) { done(err); } @@ -279,7 +403,6 @@ describe('txPool', function () { expect(readyTxs[1].receivedAt).to.equal(readyTxs[2].receivedAt); expect(readyTxs[2].receivedAt).to.equal(readyTxs[3].receivedAt); expect(readyTxs[3].receivedAt).to.equal(readyTxs[4].receivedAt); - expect(readyTxs[4].receivedAt).to.equal(readyTxs[5].receivedAt); done(); }); @@ -329,6 +452,24 @@ describe('txPool', function () { describe('process worker', function () { + it('should be ok when checked account balance with enough LSK for transaction', function (done) { + txPool.checkBalance(transactions[5], transactions[5].senderId, function (err, cbBalance) { + if (err) { + done(err); + } + expect(cbBalance).to.equal('balance: 52999955.9'); + done(); + }); + }); + + it('should fail when checked account balance with not enough LSK for transaction', function (done) { + txPool.checkBalance(transactions[6], transactions[6].senderId, function (err, cbBalance) { + if (err) { + expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); + done(); + } + }); + }); }); describe('getters', function () { From 15251a778a15d8ff8582e3ee7a26153fb6debf87 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Mon, 18 Sep 2017 09:23:24 +0200 Subject: [PATCH 13/86] Invalid txs list --- logic/transactions/pool.js | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e61594c067a..e3a0bbdf202 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -56,7 +56,7 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE pending: { transactions: {}, count: 0 }, ready: { transactions: {}, count: 0 } }, - invalid: { ids: {}, count: 0 } + invalid: {} }; // Bundled transaction timer @@ -82,6 +82,13 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE } jobsQueue.register('txPoolNextExpiry', nextExpiry, self.poolExpiryInterval); + + // Invalid transactions reset timer + function nextReset () { + library.logger.debug(['Cleared invalid txs:', self.resetInvalidTransactions()].join(' ')); + } + + jobsQueue.register('txPoolNextReset', nextReset, self.poolExpiryInterval * 10); } @@ -153,6 +160,9 @@ __private.add = function (transaction, poolList, cb) { if (__private.countTxsPool() >= self.poolStorageTxsLimit) { return setImmediate(cb, 'Transaction pool is full'); } + if (pool.invalid[transaction.id] !== undefined) { + return setImmediate(cb, 'Transaction is invalid'); + } if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); } else { @@ -575,11 +585,13 @@ TxPool.prototype.processPool = function (cb) { __private.processUnverifiedTransaction(transaction, true, function (err, sender) { if (err) { library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); + pool.invalid[transaction.id] = true; return setImmediate(eachSeriesCb); } - self.checkBalance(transaction, sender, function (err) { + self.checkBalance(transaction, sender, function (err, balance) { if (err) { library.logger.error('Failed to check balance transaction: ' + transaction.id, err); + return setImmediate(eachSeriesCb); } transaction.receivedAt = new Date(); if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures || transaction.receivedAt < transaction.timestamp)) { @@ -633,5 +645,18 @@ TxPool.prototype.expireTransactions = function (cb) { }); }; +/** + * Reset invalid transactions. + */ +TxPool.prototype.resetInvalidTransactions = function () { + var counter = 0; + + for (var tx in pool.invalid) { + delete pool.invalid[tx]; + counter++; + } + return counter; +}; + // Export module.exports = TxPool; \ No newline at end of file From 4c3346548ea92f894defb968c3a84a81052a05cc Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Mon, 18 Sep 2017 21:47:53 +0200 Subject: [PATCH 14/86] Clear index reference, fix tx receipts balance --- logic/transactions/pool.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e3a0bbdf202..3d443163353 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -187,15 +187,15 @@ __private.addReady = function (transaction, poolList, cb) { }; /** - * Deletes id from pool list index. + * Deletes id from pool list. * @param {string} id * @param {Object} poolList * @return {boolean} true if transaction id is on the list and was deleted */ __private.delete = function (id, poolList) { - var index = poolList.transactions[id]; + var tx = poolList.transactions[id]; - if (index !== undefined) { + if (tx !== undefined) { delete poolList.transactions[id]; poolList.count--; return true; @@ -278,10 +278,6 @@ __private.transactionTimeOut = function (transaction) { * @returns {setImmediateCallback} errors | sender */ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { - if (!transaction) { - return setImmediate(cb, 'Missing transaction'); - } - async.waterfall([ function setAccountAndGet (waterCb) { modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); @@ -354,7 +350,7 @@ TxPool.prototype.bind = function (accounts, transactions) { }; /** - * Gets unverified, verified.pending and verified.ready indexes and transactions length. + * Gets unverified, verified.pending and verified.ready counters. * @return {Object} unverified, pending, ready */ TxPool.prototype.getUsage = function () { @@ -436,7 +432,7 @@ TxPool.prototype.getAll = function (filter, params) { * @return {[transaction]} */ TxPool.prototype.getReady = function (limit) { - var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'desc']); + var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'asc']); if (limit && limit < r.length) { r.splice(limit); } @@ -477,7 +473,7 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { if (receiptTxs[receiptTxList].length > 0) { receiptTxs[receiptTxList].forEach(function (receiptTx) { if (receiptTx.type === transactionTypes.SEND) { - poolBalance = poolBalance.plus(paymentTx.amount.toString()); + poolBalance = poolBalance.plus(receiptTx.amount.toString()); } }); } @@ -580,6 +576,10 @@ TxPool.prototype.delete = function (transaction) { TxPool.prototype.processPool = function (cb) { async.series({ processUnverified: function (seriesCb) { + if (pool.unverified.count === 0) { + return setImmediate(seriesCb); + } + async.eachSeries(pool.unverified.transactions, function (transaction, eachSeriesCb) { __private.delete(transaction.id, pool.unverified); __private.processUnverifiedTransaction(transaction, true, function (err, sender) { @@ -607,6 +607,10 @@ TxPool.prototype.processPool = function (cb) { }); }, processPending: function (seriesCb) { + if (pool.verified.pending.count === 0) { + return setImmediate(seriesCb); + } + // process pool.verified.pending (multisig txs signs), and take care // about moving transactions from `verified.pending` to `verified.ready` async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { From b55a562d47267f979153ee1ae7efce8b7df0e7b2 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 20 Sep 2017 14:58:20 +0200 Subject: [PATCH 15/86] Count invalid txs --- logic/transactions/pool.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 3d443163353..53bc6ed3979 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -56,7 +56,7 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE pending: { transactions: {}, count: 0 }, ready: { transactions: {}, count: 0 } }, - invalid: {} + invalid: { transactions: {}, count: 0 } }; // Bundled transaction timer @@ -160,8 +160,8 @@ __private.add = function (transaction, poolList, cb) { if (__private.countTxsPool() >= self.poolStorageTxsLimit) { return setImmediate(cb, 'Transaction pool is full'); } - if (pool.invalid[transaction.id] !== undefined) { - return setImmediate(cb, 'Transaction is invalid'); + if (pool.invalid.transactions[transaction.id] !== undefined) { + return setImmediate(cb, 'Transaction is invalid: ' + transaction.id); } if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); @@ -232,7 +232,6 @@ __private.expireTxsFromList = function (poolList, parentIds, cb) { var timeNow = Math.floor(Date.now() / 1000); var timeOut = __private.transactionTimeOut(transaction); // transaction.receivedAt is instance of Date - console.log('expireTransactions - transaction.receivedAt',transaction.receivedAt); var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); if (seconds > timeOut) { @@ -350,14 +349,15 @@ TxPool.prototype.bind = function (accounts, transactions) { }; /** - * Gets unverified, verified.pending and verified.ready counters. + * Gets invalid, unverified, verified.pending and verified.ready counters. * @return {Object} unverified, pending, ready */ TxPool.prototype.getUsage = function () { return { unverified: pool.unverified.count, pending: pool.verified.pending.count, - ready: pool.verified.ready.count + ready: pool.verified.ready.count, + invalid: pool.invalid.count }; }; @@ -449,13 +449,13 @@ TxPool.prototype.getReady = function (limit) { TxPool.prototype.checkBalance = function (transaction, sender, cb) { var poolBalance = new bignum('0'), paymentTxs, receiptTxs; - library.logic.account.get({ address: sender }, 'balance', function (err, account) { + library.logic.account.get({ address: sender.address }, 'balance', function (err, account) { if (err) { return setImmediate(cb, err); } // total payments - paymentTxs = self.getAll('sender_id', { id: sender }); + paymentTxs = self.getAll('sender_id', { id: sender.address }); ['unverified','pending','ready'].forEach(function (paymentTxList) { if (paymentTxs[paymentTxList].length > 0) { paymentTxs[paymentTxList].forEach(function (paymentTx) { @@ -468,7 +468,7 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { }); // total receipts - receiptTxs = self.getAll('recipient_id', { id: sender }); + receiptTxs = self.getAll('recipient_id', { id: sender.address }); ['unverified','pending','ready'].forEach(function (receiptTxList) { if (receiptTxs[receiptTxList].length > 0) { receiptTxs[receiptTxList].forEach(function (receiptTx) { @@ -489,7 +489,7 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { if (exceeded) { return setImmediate(cb, [ - 'Account does not have enough LSK:', sender, + 'Account does not have enough LSK:', sender.address, 'balance:', balance.div(Math.pow(10,8)) ].join(' ')); } @@ -585,7 +585,8 @@ TxPool.prototype.processPool = function (cb) { __private.processUnverifiedTransaction(transaction, true, function (err, sender) { if (err) { library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); - pool.invalid[transaction.id] = true; + pool.invalid.transactions[transaction.id] = true; + pool.invalid.count++; return setImmediate(eachSeriesCb); } self.checkBalance(transaction, sender, function (err, balance) { @@ -655,10 +656,11 @@ TxPool.prototype.expireTransactions = function (cb) { TxPool.prototype.resetInvalidTransactions = function () { var counter = 0; - for (var tx in pool.invalid) { - delete pool.invalid[tx]; + for (var tx in pool.invalid.transactions) { + delete pool.invalid.transactions[tx]; counter++; } + pool.invalid.count = 0; return counter; }; From 83a0035d0e54a586e135e58c3ec61d49af78b4c8 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 20 Sep 2017 15:02:15 +0200 Subject: [PATCH 16/86] processPool tx type 0 --- test/unit/logic/transactions/pool.js | 201 +++++++++++++++++++++++---- 1 file changed, 173 insertions(+), 28 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 5a7d4df4722..46014eccf56 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -1,6 +1,7 @@ 'use strict'; var expect = require('chai').expect; +var sinon = require('sinon'); var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); @@ -8,18 +9,26 @@ var Transaction = require('../../../../logic/transaction.js'); var Account = require('../../../../logic/account.js'); var bson = require('../../../../helpers/bson.js'); +var transactionTypes = require('../../../../helpers/transactionTypes'); +var Vote = require('../../../../logic/vote.js'); +var Transfer = require('../../../../logic/transfer.js'); +var Delegate = require('../../../../logic/delegate.js'); +var Signature = require('../../../../logic/signature.js'); +var Multisignature = require('../../../../logic/multisignature.js'); + + var transactions = [ /* type: 0 - Transmit funds */ { 'type': 0, 'amount': 300000000, 'fee': 10000000, - 'timestamp': 37943880, 'recipientId': '2896019180726908125L', - 'senderId': '2737453412992791987L', 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '1' + 'timestamp': 41721274, + 'asset': {}, + 'signature': '07c2c8622000bdfb97e1321d889cef40d7ca7faee4493f220edafd3e56fd15c425a1549b50faa91affbccaf54de406fbe047c70407d1e9f7ef637941539fb30e', + 'id': '14274723388740956065' }, /* type: 1 - Register a second signature */ { @@ -60,8 +69,11 @@ var transactions = [ 'amount': 0, 'timestamp': 37943883, 'fee': 100000000, - 'asset': { - 'votes': [] + 'asset': { + 'votes': [ + '+9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f', + '-141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a' + ] }, 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', 'senderId': '2737453412992791987L', @@ -70,23 +82,24 @@ var transactions = [ }, /* type: 4 - Multisignature registration */ { - 'type': 4, - 'timestamp': 37943884, - 'fee': 1000000000, - 'asset': { - 'multisignature': { - 'min': 2, - 'lifetime': 24, - 'keysgroup': [ - "+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb", - "+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5" - ] - } - }, + 'type': 4, + 'amount': 0, + 'fee': 1500000000, + 'recipientId': null, 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'senderId': '2737453412992791987L', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '5' + 'timestamp': 41724474, + 'asset': { + 'multisignature': { + 'min': 2, + 'lifetime': 1, + 'keysgroup': [ + '+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + '+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' + ] + } + }, + 'signature': 'ee0eff648d2f48d72bdbc3f0b4dc57910cf5415a7dd70e8d4c1bfa3ab3cbbe7dd7bac730b0484be744edd6aa136569a37929d749ffe987f872dffa0bd7083d04', + 'id': '16356401289337657230' }, /* type: 0 - Transmit funds */ { @@ -126,6 +139,44 @@ var extraTransaction = { 'id': '8' }; +var invalidsTxs = [ + /* type: 0 - Transmit funds invalid senderId and recipientId*/ + { + 'type': 0, + 'amount': 300000000, + 'fee': 10000000, + 'timestamp': 37943880, + 'recipientId': '09876543210987654321L', + 'senderId': '12345678901234567890L', + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', + 'id': '9' + }, + {}, + {}, + {}, + { + 'type': 4, + 'amount': 0, + 'fee': 1500000000, + 'recipientId': null, + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'timestamp': 41725704, + 'asset': { + 'multisignature': { + 'min': 2, + 'lifetime': 1, + 'keysgroup': [ + '+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + '+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' + ] + } + }, + 'signature': '6f3e29e8e4d16f3e808133f6bf73858a3e2a932e19173260a4aaf78041399de67ef505186360a8f11a4b6b471f4f146bb9cbb388e3deb12e19540b8524a8760d', + 'id': '2761953166306398206' + } +]; + var testAccounts = [ { account: { @@ -166,6 +217,28 @@ var testAccounts = [ } ]; +// Set spies for logger +var debug = sinon.stub(modulesLoader.scope.logger, 'debug'); +var info = sinon.stub(modulesLoader.scope.logger, 'info'); +var warn = sinon.stub(modulesLoader.scope.logger, 'warn'); +var error = sinon.stub(modulesLoader.scope.logger, 'error'); + +function resetSpiesState () { + // Reset state of spies + debug.reset(); + info.reset(); + warn.reset(); + error.reset(); +} + +function restoreSpiesState () { + // Restore state of spies + debug.restore(); + info.restore(); + warn.restore(); + error.restore(); +} + describe('txPool', function () { var accounts; @@ -177,7 +250,7 @@ describe('txPool', function () { before(function (done) { modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; - modulesLoader.scope.config.transactions.poolProcessInterval = 6000; + modulesLoader.scope.config.transactions.poolProcessInterval = 60000000; modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; modulesLoader.initLogicWithDb(Account, function (err, __accountLogic) { @@ -217,12 +290,25 @@ describe('txPool', function () { ); __modules.accounts.onBind(__modules); accounts = __modules.accounts; + __trsLogic.attachAssetType(transactionTypes.VOTE, new Vote()); + __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); + __trsLogic.attachAssetType(transactionTypes.DELEGATE, new Delegate()); + __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature()); + __trsLogic.attachAssetType(transactionTypes.MULTI, new Multisignature()); done(); }); }); }, modulesLoader.scope); }); + beforeEach(function () { + resetSpiesState(); + }); + + after(function () { + restoreSpiesState(); + }); + describe('setup database', function () { it('should be ok when generate account 1', function (done) { @@ -266,6 +352,68 @@ describe('txPool', function () { }); }); + describe('process workers', function () { + + describe('processPool', function () { + + describe('Tx type: 0 - Transmit funds', function () { + + it('should be ok when add transaction type 0 to unverified', function (done) { + txPool.add(transactions[0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add invalid transaction type 0 to unverified', function (done) { + txPool.add(invalidsTxs[0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + if (err) { + done(err); + } + expect(error.args[0][0]).to.equal('Failed to process unverified transaction: 9'); + expect(error.args[10][1]).to.equal('Invalid transaction id'); + done(); + }); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(0); + expect(totals.pending).to.be.equal(0); + expect(totals.ready).to.be.equal(1); + expect(totals.invalid).to.be.equal(1); + poolTotals = totals; + done(); + }); + + it('should fail when add same invalid transaction type 0 to unverified', function (done) { + txPool.add(invalidsTxs[0], function (err, cbtx) { + expect(err).to.equal('Transaction is invalid: ' + invalidsTxs[0].id); + done(); + }); + }); + }); + }); + + describe('expireTransactions', function () { + }); + }); + describe('unverified', function () { describe('method add', function () { @@ -277,6 +425,7 @@ describe('txPool', function () { expect(totals.unverified).to.be.a('number'); expect(totals.pending).to.be.a('number'); expect(totals.ready).to.be.a('number'); + expect(totals.invalid).to.be.a('number'); poolTotals = totals; done(); }); @@ -450,7 +599,7 @@ describe('txPool', function () { }); }); - describe('process worker', function () { + describe('checkBalance', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { txPool.checkBalance(transactions[5], transactions[5].senderId, function (err, cbBalance) { @@ -573,9 +722,5 @@ describe('txPool', function () { }); }); }); - - describe('next', function () { - - }); }); }); \ No newline at end of file From c743af24f2aaf563d89b93c43985685b449a841d Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 20 Sep 2017 15:10:00 +0200 Subject: [PATCH 17/86] No need to track deleted id txs --- logic/transactions/pool.js | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 53bc6ed3979..8522e50309b 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -217,13 +217,10 @@ __private.countTxsPool = function () { * @implements {__private.transactionTimeOut} * @implements {__private.delete} * @param {Object[]} poolList - * @param {string[]} parentIds * @param {function} cb - Callback function - * @return {setImmediateCallback} error | ids[] + * @return {setImmediateCallback} cb|error */ -__private.expireTxsFromList = function (poolList, parentIds, cb) { - var ids = []; - +__private.expireTxsFromList = function (poolList, cb) { async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { if (!transaction) { return setImmediate(eachSeriesCb); @@ -235,7 +232,6 @@ __private.expireTxsFromList = function (poolList, parentIds, cb) { var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); if (seconds > timeOut) { - ids.push(transaction.id); __private.delete(poolList, transaction.id); library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); return setImmediate(eachSeriesCb); @@ -243,7 +239,7 @@ __private.expireTxsFromList = function (poolList, parentIds, cb) { return setImmediate(eachSeriesCb); } }, function (err) { - return setImmediate(cb, err, ids.concat(parentIds)); + return setImmediate(cb, err); }); }; @@ -630,23 +626,22 @@ TxPool.prototype.processPool = function (cb) { * Expires transactions. * @implements {__private.expireTxsFromList} * @param {function} cb - Callback function. - * @return {setImmediateCallback} error | ids[] + * @return {setImmediateCallback} error, cb */ TxPool.prototype.expireTransactions = function (cb) { - var ids = []; async.waterfall([ function (seriesCb) { - __private.expireTxsFromList(pool.unverified, ids, seriesCb); + __private.expireTxsFromList(pool.unverified, seriesCb); }, function (res, seriesCb) { - __private.expireTxsFromList(pool.verified.pending, ids, seriesCb); + __private.expireTxsFromList(pool.verified.pending, seriesCb); }, function (res, seriesCb) { - __private.expireTxsFromList(pool.verified.ready, ids, seriesCb); + __private.expireTxsFromList(pool.verified.ready, seriesCb); } - ], function (err, ids) { - return setImmediate(cb, err, ids); + ], function (err) { + return setImmediate(cb, err); }); }; From 22e5a258d622111ffb2cb749201a7a09868c878a Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 4 Oct 2017 10:03:11 +0200 Subject: [PATCH 18/86] Check balance only from ready list --- logic/transactions/pool.js | 65 ++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 8522e50309b..69db477f4ab 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -7,6 +7,7 @@ var constants = require('../../helpers/constants.js'); var jobsQueue = require('../../helpers/jobsQueue.js'); var transactionTypes = require('../../helpers/transactionTypes.js'); var bignum = require('../../helpers/bignum.js'); +var slots = require('../../helpers/slots.js'); // Private fields var modules, library, self, __private = {}, pool = {}; @@ -161,7 +162,7 @@ __private.add = function (transaction, poolList, cb) { return setImmediate(cb, 'Transaction pool is full'); } if (pool.invalid.transactions[transaction.id] !== undefined) { - return setImmediate(cb, 'Transaction is invalid: ' + transaction.id); + return setImmediate(cb, 'Transaction is already processed as invalid: ' + transaction.id); } if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); @@ -186,6 +187,15 @@ __private.addReady = function (transaction, poolList, cb) { return setImmediate(cb); }; +/** + * Adds transaction id to invalid pool list. + * @param {string} id + */ +__private.addInvalid = function (id) { + pool.invalid.transactions[id] = true; + pool.invalid.count++; +}; + /** * Deletes id from pool list. * @param {string} id @@ -239,7 +249,7 @@ __private.expireTxsFromList = function (poolList, cb) { return setImmediate(eachSeriesCb); } }, function (err) { - return setImmediate(cb, err); + return setImmediate(cb, err, null); }); }; @@ -299,6 +309,7 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { function processTransaction (sender, requester, waterCb) { library.logic.transaction.process(transaction, sender, requester, function (err) { if (err) { + __private.addInvalid(transaction.id); return setImmediate(waterCb, err); } else { return setImmediate(waterCb, null, sender); @@ -310,12 +321,14 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { transaction = library.logic.transaction.objectNormalize(transaction); return setImmediate(waterCb, null, sender); } catch (err) { + __private.addInvalid(transaction.id); return setImmediate(waterCb, err); } }, function verifyTransaction (sender, waterCb) { library.logic.transaction.verify(transaction, sender, function (err) { if (err) { + __private.addInvalid(transaction.id); return setImmediate(waterCb, err); } else { return setImmediate(waterCb, null, sender); @@ -324,7 +337,7 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { } ], function (err, sender) { if (!err) { - library.bus.message('unconfirmedTransaction', transaction, broadcast); + library.bus.message('unverifiedTransaction', transaction, broadcast); } return setImmediate(cb, err, sender); @@ -404,7 +417,7 @@ TxPool.prototype.get = function (id) { TxPool.prototype.getAll = function (filter, params) { switch (filter) { case 'unverified': - return __private.getTxsFromPoolList(pool.unverified.transactions, params.reverse, params.limit); + return __private.getTxsFromPoolList(pool.unverified.transactions, params.limit); case 'pending': return __private.getTxsFromPoolList(pool.verified.pending.transactions, params.reverse, params.limit); case 'ready': @@ -443,7 +456,9 @@ TxPool.prototype.getReady = function (limit) { * @return {setImmediateCallback} err, transactions */ TxPool.prototype.checkBalance = function (transaction, sender, cb) { - var poolBalance = new bignum('0'), paymentTxs, receiptTxs; + var poolBalance = new bignum('0'); + var paymentTxs; + var receiptTxs; library.logic.account.get({ address: sender.address }, 'balance', function (err, account) { if (err) { @@ -452,28 +467,24 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { // total payments paymentTxs = self.getAll('sender_id', { id: sender.address }); - ['unverified','pending','ready'].forEach(function (paymentTxList) { - if (paymentTxs[paymentTxList].length > 0) { - paymentTxs[paymentTxList].forEach(function (paymentTx) { - if (paymentTx.amount) { - poolBalance = poolBalance.minus(paymentTx.amount.toString()); - } - poolBalance = poolBalance.minus(paymentTx.fee.toString()); - }); - } - }); + if (paymentTxs.ready.length > 0) { + paymentTxs.ready.forEach(function (paymentTx) { + if (paymentTx.amount) { + poolBalance = poolBalance.minus(paymentTx.amount.toString()); + } + poolBalance = poolBalance.minus(paymentTx.fee.toString()); + }); + } // total receipts receiptTxs = self.getAll('recipient_id', { id: sender.address }); - ['unverified','pending','ready'].forEach(function (receiptTxList) { - if (receiptTxs[receiptTxList].length > 0) { - receiptTxs[receiptTxList].forEach(function (receiptTx) { - if (receiptTx.type === transactionTypes.SEND) { - poolBalance = poolBalance.plus(receiptTx.amount.toString()); - } - }); - } - }); + if (receiptTxs.ready.length > 0) { + receiptTxs.ready.forEach(function (receiptTx) { + if (receiptTx.type === transactionTypes.SEND) { + poolBalance = poolBalance.plus(receiptTx.amount.toString()); + } + }); + } // total balance var balance = new bignum(account.balance.toString()); @@ -581,8 +592,6 @@ TxPool.prototype.processPool = function (cb) { __private.processUnverifiedTransaction(transaction, true, function (err, sender) { if (err) { library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); - pool.invalid.transactions[transaction.id] = true; - pool.invalid.count++; return setImmediate(eachSeriesCb); } self.checkBalance(transaction, sender, function (err, balance) { @@ -591,7 +600,9 @@ TxPool.prototype.processPool = function (cb) { return setImmediate(eachSeriesCb); } transaction.receivedAt = new Date(); - if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures || transaction.receivedAt < transaction.timestamp)) { + var receiveAtToTime = transaction.receivedAt.getTime(); + var timestampToTime = slots.getRealTime(transaction.timestamp); + if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { __private.add(transaction, pool.verified.pending, eachSeriesCb); } else { // check transaction and if ok add to verified.ready From 189ff9ee126d8ac3022b7c30d34d1ee82d92d0ba Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 4 Oct 2017 10:29:09 +0200 Subject: [PATCH 19/86] Delete reverse option for txs list return --- logic/transactions/pool.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 69db477f4ab..569528c5734 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -95,23 +95,17 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE // Private /** - * Gets reversed or limited transactions from input parameter. + * Gets all or limited number of transactions from input array. * @private * @param {transaction[]} transactions - * @param {boolean} reverse * @param {number} limit * @return {transaction[]} */ -__private.getTxsFromPoolList = function (transactions, reverse, limit) { +__private.getTxsFromPoolList = function (transactions, limit) { var txs; - if (reverse || limit){ - txs = Object.keys(transactions).reverse(); - } - if (reverse) { - txs = txs.reverse(); - } + if (limit) { - txs.splice(limit); + txs = Object.keys(transactions).splice(limit); } return txs; @@ -419,9 +413,9 @@ TxPool.prototype.getAll = function (filter, params) { case 'unverified': return __private.getTxsFromPoolList(pool.unverified.transactions, params.limit); case 'pending': - return __private.getTxsFromPoolList(pool.verified.pending.transactions, params.reverse, params.limit); + return __private.getTxsFromPoolList(pool.verified.pending.transactions, params.limit); case 'ready': - return __private.getTxsFromPoolList(pool.verified.ready.transactions, params.reverse, params.limit); + return __private.getTxsFromPoolList(pool.verified.ready.transactions, params.limit); case 'sender_id': return __private.getAllPoolTxsByFilter({'senderId': params.id}); case 'sender_pk': From 165a8b215fd62b75765df1bc468e5fcf0a6842b7 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 4 Oct 2017 10:56:22 +0200 Subject: [PATCH 20/86] Test tx type 0 --- test/unit/logic/transactions/pool.js | 227 +++++++++++++++++---------- 1 file changed, 145 insertions(+), 82 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 46014eccf56..2c02ff0cc64 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -2,7 +2,7 @@ var expect = require('chai').expect; var sinon = require('sinon'); - +var _ = require('lodash'); var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); @@ -34,17 +34,17 @@ var transactions = [ { 'type': 1, 'amount': 0, - 'timestamp': 37943881, 'fee': 500000000, + 'recipientId': null, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'timestamp': 41808966, 'asset': { 'signature': { - 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' + 'publicKey': '8ccfeb0e05a84124fb8e9932ea5d1744617907ef5b51ffde12e24a805ae992fa' } }, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'senderId': '2737453412992791987L', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '2' + 'signature': '82dc975a49b5fcb19d05b736f7c53978c9973619ef2822e0dfaf0160e1d21a7c5ceb81abb62ebcacfa1c8c3a501035103e252d65fbd5518e38db71f7acc3c20d', + 'id': '16927110199431968159' }, /* type: 2 - Register a delegate */ { @@ -113,18 +113,6 @@ var transactions = [ 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', 'id': '6' }, - /* type: 0 - Transmit funds Account does not have enough LSK*/ - { - 'type': 0, - 'amount': 800000000, - 'fee': 10000000, - 'timestamp': 37943885, - 'recipientId': '2737453412992791987L', - 'senderId': '2896019180726908125L', - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '7' - } ]; var extraTransaction = { @@ -140,21 +128,36 @@ var extraTransaction = { }; var invalidsTxs = [ - /* type: 0 - Transmit funds invalid senderId and recipientId*/ + /* type: 0 - Transmit funds account without enough credit*/ { 'type': 0, - 'amount': 300000000, + 'amount': 4400000000, 'fee': 10000000, - 'timestamp': 37943880, - 'recipientId': '09876543210987654321L', - 'senderId': '12345678901234567890L', + 'recipientId': '2737453412992791987L', + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'timestamp': 42412477, + 'asset': {}, + 'signature': '90e303cb9d547acb680852c8fd583b3c798011e9e01739cd4755f8b4a34607157a9629441e3a2093f46f441de3ed6609080be1e5a2bf13c46b8cfea68d4ada09', + 'id': '5123711709529859173' + }, + /* type: 1 - Register a second signature account without enough credit*/ + { + 'type': 1, + 'amount': 0, + 'fee': 500000000, + 'recipientId': null, 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '9' + 'timestamp': 41808966, + 'asset': { + 'signature': { + 'publicKey': '8ccfeb0e05a84124fb8e9932ea5d1744617907ef5b51ffde12e24a805ae992fa' + } + }, + 'signature': '82dc975a49b5fcb19d05b736f7c53978c9973619ef2822e0dfaf0160e1d21a7c5ceb81abb62ebcacfa1c8c3a501035103e252d65fbd5518e38db71f7acc3c20d', + 'id': '16927110199431968159' }, {}, {}, - {}, { 'type': 4, 'amount': 0, @@ -175,6 +178,7 @@ var invalidsTxs = [ 'signature': '6f3e29e8e4d16f3e808133f6bf73858a3e2a932e19173260a4aaf78041399de67ef505186360a8f11a4b6b471f4f146bb9cbb388e3deb12e19540b8524a8760d', 'id': '2761953166306398206' } + /* type: 0 - Transmit funds invalid senderId and recipientId*/ ]; var testAccounts = [ @@ -354,11 +358,24 @@ describe('txPool', function () { describe('process workers', function () { + it('should be ok when get pool totals to initialize local counter', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.a('number'); + expect(totals.pending).to.be.a('number'); + expect(totals.ready).to.be.a('number'); + expect(totals.invalid).to.be.a('number'); + poolTotals = totals; + done(); + }); + describe('processPool', function () { describe('Tx type: 0 - Transmit funds', function () { + var tmpTxInvalid_Id; - it('should be ok when add transaction type 0 to unverified', function (done) { + it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { if (err) { done(err); @@ -367,8 +384,8 @@ describe('txPool', function () { done(); }); }); - - it('should be ok when add invalid transaction type 0 to unverified', function (done) { + + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[0], function (err, cbtx) { if (err) { done(err); @@ -377,6 +394,82 @@ describe('txPool', function () { done(); }); }); + + it('should be ok when add transaction to unverified with invalid id', function (done) { + tmpTxInvalid_Id = _.cloneDeep(invalidsTxs[0]); + tmpTxInvalid_Id.id = '1234567890123456789'; + + txPool.add(tmpTxInvalid_Id, function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + if (err) { + done(err); + } + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalid_Id.id); + expect(error.args[1][1]).to.equal('Invalid transaction id'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + done(); + }); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + + it('should fail when add same normal transaction to unverified', function (done) { + txPool.add(transactions[0], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); + done(); + }); + }); + + it('should fail when add same transaction with invalid id to unverified', function (done) { + txPool.add(tmpTxInvalid_Id, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalid_Id.id); + done(); + }); + }); + }); + + describe('Tx type: 1 - Register a second signature', function () { + + it('should be ok when add transaction to unverified', function (done) { + txPool.add(transactions[1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add invalid transaction to unverified', function (done) { + txPool.add(invalidsTxs[1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { @@ -384,7 +477,9 @@ describe('txPool', function () { done(err); } expect(error.args[0][0]).to.equal('Failed to process unverified transaction: 9'); - expect(error.args[10][1]).to.equal('Invalid transaction id'); + expect(error.args[0][1]).to.equal('Invalid transaction id'); + poolTotals.ready += 1; + poolTotals.invalid += 1; done(); }); }); @@ -393,17 +488,23 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.unverified).to.be.equal(0); - expect(totals.pending).to.be.equal(0); - expect(totals.ready).to.be.equal(1); - expect(totals.invalid).to.be.equal(1); - poolTotals = totals; + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); done(); }); - it('should fail when add same invalid transaction type 0 to unverified', function (done) { - txPool.add(invalidsTxs[0], function (err, cbtx) { - expect(err).to.equal('Transaction is invalid: ' + invalidsTxs[0].id); + it('should fail when add same transaction to unverified', function (done) { + txPool.add(transactions[1], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); + done(); + }); + }); + + it('should fail when add same invalid transaction to unverified', function (done) { + txPool.add(invalidsTxs[1], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[1].id); done(); }); }); @@ -418,46 +519,8 @@ describe('txPool', function () { describe('method add', function () { - it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); - - expect(totals).to.be.an('object'); - expect(totals.unverified).to.be.a('number'); - expect(totals.pending).to.be.a('number'); - expect(totals.ready).to.be.a('number'); - expect(totals.invalid).to.be.a('number'); - poolTotals = totals; - done(); - }); - - it('should be ok when add transaction type 0 to unverified', function (done) { - txPool.add(transactions[0], function (err, cbtx) { - if (err) { - done(err); - } - expect(cbtx).to.be.undefined; - done(); - }); - }); - - it('should be ok when check unverified value increased in 1', function (done) { - var totals = txPool.getUsage(); - - expect(totals).to.be.an('object'); - expect(totals.unverified).to.equal(poolTotals.unverified + 1); - poolTotals = totals; - done(); - }); - - it('should fail when add same transaction type 0 to unverified', function (done) { - txPool.add(transactions[0], function (err, cbtx) { - expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); - done(); - }); - }); - it('should be ok when add transactions to fill pool storage', function (done) { - var trx = transactions.slice(1,transactions.length-1); + var trx = transactions.slice(1,transactions.length-2); txPool.add(trx, function (err, cbtx) { if (err) { done(err); @@ -659,25 +722,25 @@ describe('txPool', function () { describe('by pool list', function () { it('should be ok when pool list is unverified', function (done) { - var txs = txPool.getAll('unverified', { reverse: true, limit: null}); + var txs = txPool.getAll('unverified', { limit: null}); expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is pending', function (done) { - var txs = txPool.getAll('pending', { reverse: true, limit: null}); + var txs = txPool.getAll('pending', { limit: null}); expect(txs.length).to.equal(0); done(); }); it('should be ok when pool list is ready', function (done) { - var txs = txPool.getAll('ready', { reverse: true, limit: null}); + var txs = txPool.getAll('ready', { limit: null}); expect(txs.length).to.equal(5); done(); }); it('should fail when filter is invalid', function (done) { - var txs = txPool.getAll('unknown', { reverse: true, limit: null}); + var txs = txPool.getAll('unknown', { limit: null}); expect(txs).to.equal('Invalid filter'); done(); }); From 4765a21d46a955260dc1fd63ac6ff71865e61e30 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 4 Oct 2017 13:02:20 +0200 Subject: [PATCH 21/86] Test tx type 1 --- test/unit/logic/transactions/pool.js | 139 ++++++++++++++++++--------- 1 file changed, 95 insertions(+), 44 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 2c02ff0cc64..6c818cbb265 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -146,15 +146,15 @@ var invalidsTxs = [ 'amount': 0, 'fee': 500000000, 'recipientId': null, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'timestamp': 41808966, + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'timestamp': 42999044, 'asset': { 'signature': { 'publicKey': '8ccfeb0e05a84124fb8e9932ea5d1744617907ef5b51ffde12e24a805ae992fa' } }, - 'signature': '82dc975a49b5fcb19d05b736f7c53978c9973619ef2822e0dfaf0160e1d21a7c5ceb81abb62ebcacfa1c8c3a501035103e252d65fbd5518e38db71f7acc3c20d', - 'id': '16927110199431968159' + 'signature': '30fb1a449dc132a30fa18ad0e905f4702b19dd5199767b8c3a1673173e8905c75a9163980d2c2a06d48faec6a778139cb1fa784a1cbbaa929395675a64231100', + 'id': '7078486003124131749' }, {}, {}, @@ -294,10 +294,10 @@ describe('txPool', function () { ); __modules.accounts.onBind(__modules); accounts = __modules.accounts; - __trsLogic.attachAssetType(transactionTypes.VOTE, new Vote()); + __trsLogic.attachAssetType(transactionTypes.VOTE, new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema)); __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); __trsLogic.attachAssetType(transactionTypes.DELEGATE, new Delegate()); - __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature()); + __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature(modulesLoader.scope.schema, modulesLoader.scope.logger)); __trsLogic.attachAssetType(transactionTypes.MULTI, new Multisignature()); done(); }); @@ -373,7 +373,7 @@ describe('txPool', function () { describe('processPool', function () { describe('Tx type: 0 - Transmit funds', function () { - var tmpTxInvalid_Id; + var tmpTxInvalidId; it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { @@ -396,10 +396,10 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified with invalid id', function (done) { - tmpTxInvalid_Id = _.cloneDeep(invalidsTxs[0]); - tmpTxInvalid_Id.id = '1234567890123456789'; + tmpTxInvalidId = _.cloneDeep(invalidsTxs[0]); + tmpTxInvalidId.id = '1234567890123456789'; - txPool.add(tmpTxInvalid_Id, function (err, cbtx) { + txPool.add(tmpTxInvalidId, function (err, cbtx) { if (err) { done(err); } @@ -415,7 +415,7 @@ describe('txPool', function () { } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalid_Id.id); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidId.id); expect(error.args[1][1]).to.equal('Invalid transaction id'); poolTotals.invalid += 1; poolTotals.ready += 1; @@ -423,17 +423,6 @@ describe('txPool', function () { }); }); - it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); - - expect(totals).to.be.an('object'); - expect(totals.unverified).to.be.equal(poolTotals.unverified); - expect(totals.pending).to.be.equal(poolTotals.pending); - expect(totals.ready).to.be.equal(poolTotals.ready); - expect(totals.invalid).to.be.equal(poolTotals.invalid); - done(); - }); - it('should fail when add same normal transaction to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); @@ -442,16 +431,45 @@ describe('txPool', function () { }); it('should fail when add same transaction with invalid id to unverified', function (done) { - txPool.add(tmpTxInvalid_Id, function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalid_Id.id); + txPool.add(tmpTxInvalidId, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidId.id); done(); }); }); + + it('should be ok when delete normal transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[0]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(1); + poolTotals.invalid -= 1; + done(); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.equal(poolTotals.unverified); + expect(totals.pending).to.equal(poolTotals.pending); + expect(totals.ready).to.equal(poolTotals.ready); + expect(totals.invalid).to.equal(poolTotals.invalid); + done(); + }); }); describe('Tx type: 1 - Register a second signature', function () { + var tmpTxInvalidSenderPk; - it('should be ok when add transaction to unverified', function (done) { + it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[1], function (err, cbtx) { if (err) { done(err); @@ -461,7 +479,7 @@ describe('txPool', function () { }); }); - it('should be ok when add invalid transaction to unverified', function (done) { + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[1], function (err, cbtx) { if (err) { done(err); @@ -471,19 +489,66 @@ describe('txPool', function () { }); }); + it('should be ok when add transaction to unverified with invalid senderPublicKey', function (done) { + tmpTxInvalidSenderPk = _.cloneDeep(invalidsTxs[1]); + tmpTxInvalidSenderPk.senderPublicKey = '1234567890abcde1234567890abcde1234567890abcde1234567890abcde1234'; + tmpTxInvalidSenderPk.id = '2345678901234567890'; + + txPool.add(tmpTxInvalidSenderPk, function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { if (err) { done(err); } - expect(error.args[0][0]).to.equal('Failed to process unverified transaction: 9'); - expect(error.args[0][1]).to.equal('Invalid transaction id'); - poolTotals.ready += 1; + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[1].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSenderPk.id); + expect(error.args[1][1]).to.equal('Invalid transaction id'); poolTotals.invalid += 1; + poolTotals.ready += 1; done(); }); }); - + + it('should fail when add same normal transaction to unverified', function (done) { + txPool.add(transactions[1], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); + done(); + }); + }); + + it('should fail when add same transaction with invalid id to unverified', function (done) { + txPool.add(tmpTxInvalidSenderPk, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidSenderPk.id); + done(); + }); + }); + + it('should be ok when delete normal transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[1]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(1); + poolTotals.invalid -= 1; + done(); + }); + it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); @@ -494,20 +559,6 @@ describe('txPool', function () { expect(totals.invalid).to.be.equal(poolTotals.invalid); done(); }); - - it('should fail when add same transaction to unverified', function (done) { - txPool.add(transactions[1], function (err, cbtx) { - expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); - done(); - }); - }); - - it('should fail when add same invalid transaction to unverified', function (done) { - txPool.add(invalidsTxs[1], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[1].id); - done(); - }); - }); }); }); From f8ddc9bdf33ee5e135e623289b358327492b637b Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Wed, 11 Oct 2017 14:34:16 +0200 Subject: [PATCH 22/86] Test tx type 2 --- test/unit/logic/transactions/pool.js | 125 +++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 7 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 6c818cbb265..18192005d5f 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -156,7 +156,23 @@ var invalidsTxs = [ 'signature': '30fb1a449dc132a30fa18ad0e905f4702b19dd5199767b8c3a1673173e8905c75a9163980d2c2a06d48faec6a778139cb1fa784a1cbbaa929395675a64231100', 'id': '7078486003124131749' }, - {}, + /* type: 2 - Register a delegate account without enough credit*/ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'timestamp': 43019957, + 'asset': { + 'delegate': { + 'username': 'test_2', + 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' + } + }, + 'signature': 'd11bb8ff05dd8ae36fd7b93175d330b6f38ff96c113501667b04b02c2c225efa6920dffea0d93e5dd6ed770273685f01df1cb4090e121b3724c1ae86b6fabf02', + 'id': '13166754169713489797' + }, {}, { 'type': 4, @@ -205,7 +221,7 @@ var testAccounts = [ username: 'test_3', isDelegate: 0, address: '15240249857307028085L', - publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', balance: 3500000000000000, }, secret: 'song gather until exercise explain utility walk choice garbage cross route develop', @@ -214,7 +230,7 @@ var testAccounts = [ username: 'test_4', isDelegate: 0, address: '13898484363564790288L', - publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', balance: 3500000000000000, }, secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', @@ -395,9 +411,9 @@ describe('txPool', function () { }); }); - it('should be ok when add transaction to unverified with invalid id', function (done) { + it('should be ok when add transaction to unverified with Unknown transaction type ', function (done) { tmpTxInvalidId = _.cloneDeep(invalidsTxs[0]); - tmpTxInvalidId.id = '1234567890123456789'; + tmpTxInvalidId.id = '01234567890123456789'; txPool.add(tmpTxInvalidId, function (err, cbtx) { if (err) { @@ -416,7 +432,7 @@ describe('txPool', function () { expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidId.id); - expect(error.args[1][1]).to.equal('Invalid transaction id'); + expect(error.args[1][1]).to.equal('Unknown transaction type '); poolTotals.invalid += 1; poolTotals.ready += 1; done(); @@ -492,7 +508,7 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with invalid senderPublicKey', function (done) { tmpTxInvalidSenderPk = _.cloneDeep(invalidsTxs[1]); tmpTxInvalidSenderPk.senderPublicKey = '1234567890abcde1234567890abcde1234567890abcde1234567890abcde1234'; - tmpTxInvalidSenderPk.id = '2345678901234567890'; + tmpTxInvalidSenderPk.id = '12345678901234567890'; txPool.add(tmpTxInvalidSenderPk, function (err, cbtx) { if (err) { @@ -560,6 +576,101 @@ describe('txPool', function () { done(); }); }); + + describe('Tx type: 2 - Register a delegate', function () { + var tmpTxInvalidSignature; + + it('should be ok when add normal transaction to unverified', function (done) { + txPool.add(transactions[2], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified with not enough LSK', function (done) { + txPool.add(invalidsTxs[2], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified with invalid signature', function (done) { + tmpTxInvalidSignature = _.cloneDeep(invalidsTxs[2]); + tmpTxInvalidSignature.signature = '1234567890abcde1234567890abcde1234567890abcde1234567890abcde1234'; + tmpTxInvalidSignature.id = '23456789012345678901'; + + txPool.add(tmpTxInvalidSignature, function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + if (err) { + done(err); + } + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[2].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[2].account.address, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSignature.id); + expect(error.args[1][1]).to.equal('Invalid transaction id'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + done(); + }); + }); + + it('should fail when add same normal transaction to unverified', function (done) { + txPool.add(transactions[1], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); + done(); + }); + }); + + it('should fail when add same transaction with invalid id to unverified', function (done) { + txPool.add(tmpTxInvalidSignature, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidSignature.id); + done(); + }); + }); + + it('should be ok when delete normal transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[2]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(1); + poolTotals.invalid -= 1; + done(); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + }); }); describe('expireTransactions', function () { From ddcb2878bde38c3335b0b1869bc8d5ae9962d519 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Fri, 13 Oct 2017 12:11:45 +0200 Subject: [PATCH 23/86] Adjust test tx type 2 --- logic/transactions/pool.js | 4 +- test/unit/logic/transactions/pool.js | 209 +++++++++++++++++++-------- 2 files changed, 149 insertions(+), 64 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 569528c5734..d3a58e1c38c 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -342,12 +342,10 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { /** * Bounds input parameters to private variable modules. * @param {Accounts} accounts - * @param {Transactions} transactions */ -TxPool.prototype.bind = function (accounts, transactions) { +TxPool.prototype.bind = function (accounts) { modules = { accounts: accounts, - transactions: transactions, }; }; diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 18192005d5f..0ce77e8275a 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -50,18 +50,18 @@ var transactions = [ { 'type': 2, 'amount': 0, - 'timestamp': 37943882, 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', + 'timestamp': 43776413, 'asset': { 'delegate': { - 'username': 'test_delegate_1', - 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' + 'username': 'txp_new_delegate', + 'publicKey': '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' } }, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'senderId': '2737453412992791987L', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '3' + 'signature': '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a', + 'id': '4169182049562816689' }, /* type: 3 - Submit votes */ { @@ -156,23 +156,59 @@ var invalidsTxs = [ 'signature': '30fb1a449dc132a30fa18ad0e905f4702b19dd5199767b8c3a1673173e8905c75a9163980d2c2a06d48faec6a778139cb1fa784a1cbbaa929395675a64231100', 'id': '7078486003124131749' }, - /* type: 2 - Register a delegate account without enough credit*/ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'timestamp': 43019957, - 'asset': { - 'delegate': { - 'username': 'test_2', - 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' - } + [ + /* type: 2 - Register a delegate account without enough credit*/ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9', + 'timestamp': 43775831, + 'asset': { + 'delegate': { + 'username': 'txp_new_delegate', + 'publicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9' + } + }, + 'signature': 'c67bb4f37a2aba0c3e67292ca61fd50064ef3fb32858cbe4b34fa1469ed3978db6b682df609117c1e227156d427bc24f0a3af8bd1ae6ec9194177ad417dd1500', + 'id': '7121061506817701772' }, - 'signature': 'd11bb8ff05dd8ae36fd7b93175d330b6f38ff96c113501667b04b02c2c225efa6920dffea0d93e5dd6ed770273685f01df1cb4090e121b3724c1ae86b6fabf02', - 'id': '13166754169713489797' - }, + /* type: 2 - Register a delegate that already is delegate*/ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + 'timestamp': 43697153, + 'asset': { + 'delegate': { + 'username': 'txp_test_1', + 'publicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' + } + }, + 'signature': 'c9441e49228006e9ab9f5f676c49a56f8ec0eb23c539115912cd5b0d48f51c897d01ad2f5abd6bfac92cadbc3704bce076d1c104c63de1a28b247271c5d72601', + 'id': '358375690571860615' + }, + /* type: 2 - Register a delegate account with existing username*/ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + 'timestamp': 43697153, + 'asset': { + 'delegate': { + 'username': 'txp_test_2', + 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' + } + }, + 'signature': '3522664cfbe9a5ca3ade309a0c96add1861e29c7f0b3b9aa77177492c69a47f9f7c718dbd415ad49682215826a01579f74d728c6e1bc1c8e808d9ca3a06b8b0c', + 'id': '11660632744648534794' + } + ], {}, { 'type': 4, @@ -200,38 +236,42 @@ var invalidsTxs = [ var testAccounts = [ { account: { - username: 'test_1', + username: 'txp_test_1', isDelegate: 1, address: '2737453412992791987L', publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', balance: 5300000000000000, + u_balance: 5300000000000000 }, secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', },{ account: { - username: 'test_2', + username: 'txp_test_2', isDelegate: 0, address: '2896019180726908125L', publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', balance: 0, + u_balance: 0 }, secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', },{ account: { - username: 'test_3', + username: 'txp_test_3', isDelegate: 0, address: '15240249857307028085L', publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', balance: 3500000000000000, + u_balance: 3500000000000000 }, secret: 'song gather until exercise explain utility walk choice garbage cross route develop', },{ account: { - username: 'test_4', + username: 'txp_test_4', isDelegate: 0, address: '13898484363564790288L', publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', balance: 3500000000000000, + u_balance: 3500000000000000 }, secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', } @@ -303,18 +343,20 @@ describe('txPool', function () { if (err) { return done(err); } - txPool.bind( - __modules.accounts, - null, - __modules.loader - ); + var logicDelegates = new Delegate(modulesLoader.scope.schema); + logicDelegates.bind(__modules.accounts); + __modules.accounts.onBind(__modules); accounts = __modules.accounts; + + txPool.bind(__modules.accounts); + __trsLogic.attachAssetType(transactionTypes.VOTE, new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema)); __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); - __trsLogic.attachAssetType(transactionTypes.DELEGATE, new Delegate()); + __trsLogic.attachAssetType(transactionTypes.DELEGATE, logicDelegates); __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature(modulesLoader.scope.schema, modulesLoader.scope.logger)); __trsLogic.attachAssetType(transactionTypes.MULTI, new Multisignature()); + done(); }); }); @@ -411,7 +453,7 @@ describe('txPool', function () { }); }); - it('should be ok when add transaction to unverified with Unknown transaction type ', function (done) { + it('should be ok when add transaction to unverified with invalid transaction id', function (done) { tmpTxInvalidId = _.cloneDeep(invalidsTxs[0]); tmpTxInvalidId.id = '01234567890123456789'; @@ -432,7 +474,7 @@ describe('txPool', function () { expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidId.id); - expect(error.args[1][1]).to.equal('Unknown transaction type '); + expect(error.args[1][1]).to.equal('Invalid transaction id'); poolTotals.invalid += 1; poolTotals.ready += 1; done(); @@ -483,7 +525,7 @@ describe('txPool', function () { }); describe('Tx type: 1 - Register a second signature', function () { - var tmpTxInvalidSenderPk; + var invalidTransactionType; it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[1], function (err, cbtx) { @@ -505,12 +547,12 @@ describe('txPool', function () { }); }); - it('should be ok when add transaction to unverified with invalid senderPublicKey', function (done) { - tmpTxInvalidSenderPk = _.cloneDeep(invalidsTxs[1]); - tmpTxInvalidSenderPk.senderPublicKey = '1234567890abcde1234567890abcde1234567890abcde1234567890abcde1234'; - tmpTxInvalidSenderPk.id = '12345678901234567890'; + it('should be ok when add transaction to unverified with invalid transaction type', function (done) { + invalidTransactionType = _.cloneDeep(invalidsTxs[0]); + invalidTransactionType.id = '12345678901234567890'; + invalidTransactionType.type = 99; - txPool.add(tmpTxInvalidSenderPk, function (err, cbtx) { + txPool.add(invalidTransactionType, function (err, cbtx) { if (err) { done(err); } @@ -526,8 +568,8 @@ describe('txPool', function () { } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[1].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSenderPk.id); - expect(error.args[1][1]).to.equal('Invalid transaction id'); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidTransactionType.id); + expect(error.args[1][1]).to.equal(['Unknown transaction type', invalidTransactionType.type].join(' ')); poolTotals.invalid += 1; poolTotals.ready += 1; done(); @@ -541,9 +583,9 @@ describe('txPool', function () { }); }); - it('should fail when add same transaction with invalid id to unverified', function (done) { - txPool.add(tmpTxInvalidSenderPk, function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidSenderPk.id); + it('should fail when add same transaction with invalid transaction type to unverified', function (done) { + txPool.add(invalidTransactionType, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidTransactionType.id); done(); }); }); @@ -560,8 +602,8 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(1); - poolTotals.invalid -= 1; + expect(invalidTxs).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTxs; done(); }); @@ -591,7 +633,27 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[2], function (err, cbtx) { + txPool.add(invalidsTxs[2][0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified that already is a delegate', function (done) { + txPool.add(invalidsTxs[2][1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified with same username', function (done) { + txPool.add(invalidsTxs[2][2], function (err, cbtx) { if (err) { done(err); } @@ -601,9 +663,9 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified with invalid signature', function (done) { - tmpTxInvalidSignature = _.cloneDeep(invalidsTxs[2]); - tmpTxInvalidSignature.signature = '1234567890abcde1234567890abcde1234567890abcde1234567890abcde1234'; - tmpTxInvalidSignature.id = '23456789012345678901'; + tmpTxInvalidSignature = _.cloneDeep(invalidsTxs[2][0]); + tmpTxInvalidSignature.signature = '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a'; + tmpTxInvalidSignature.id = '16349767733713562311'; txPool.add(tmpTxInvalidSignature, function (err, cbtx) { if (err) { @@ -619,24 +681,49 @@ describe('txPool', function () { if (err) { done(err); } - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[2].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[2].account.address, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSignature.id); - expect(error.args[1][1]).to.equal('Invalid transaction id'); - poolTotals.invalid += 1; + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[2][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[2][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][1].id); + expect(error.args[1][1]).to.equal('Account is already a delegate'); + expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][2].id); + expect(error.args[2][1]).to.equal('Username already exists'); + expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSignature.id); + expect(error.args[3][1]).to.equal('Failed to verify signature'); + poolTotals.invalid += 3; poolTotals.ready += 1; done(); }); }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[1], function (err, cbtx) { + txPool.add(transactions[2], function (err, cbtx) { expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); done(); }); }); - it('should fail when add same transaction with invalid id to unverified', function (done) { + it('should fail when add same transaction with registered delegate to unverified', function (done) { + txPool.add(invalidsTxs[2][1], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][1].id); + done(); + }); + }); + + it('should fail when add same transaction with registered delegate to unverified', function (done) { + txPool.add(invalidsTxs[2][1], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][1].id); + done(); + }); + }); + + it('should fail when add same transaction with same username to unverified', function (done) { + txPool.add(invalidsTxs[2][2], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][2].id); + done(); + }); + }); + + it('should fail when add same transaction with invalid signature to unverified', function (done) { txPool.add(tmpTxInvalidSignature, function (err, cbtx) { expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidSignature.id); done(); @@ -655,8 +742,8 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(1); - poolTotals.invalid -= 1; + expect(invalidTxs).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTxs; done(); }); From 10b4511c7fc3985d0409f68233b44f2b5176b471 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Fri, 13 Oct 2017 14:18:41 +0200 Subject: [PATCH 24/86] Replace hardcoded test data with node.lisk calls --- test/unit/logic/transactions/pool.js | 280 ++++++--------------------- 1 file changed, 55 insertions(+), 225 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 0ce77e8275a..321efc114dd 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -3,6 +3,8 @@ var expect = require('chai').expect; var sinon = require('sinon'); var _ = require('lodash'); +var node = require('../../../node'); + var modulesLoader = require('../../../common/initModule').modulesLoader; var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); @@ -16,223 +18,6 @@ var Delegate = require('../../../../logic/delegate.js'); var Signature = require('../../../../logic/signature.js'); var Multisignature = require('../../../../logic/multisignature.js'); - -var transactions = [ - /* type: 0 - Transmit funds */ - { - 'type': 0, - 'amount': 300000000, - 'fee': 10000000, - 'recipientId': '2896019180726908125L', - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'timestamp': 41721274, - 'asset': {}, - 'signature': '07c2c8622000bdfb97e1321d889cef40d7ca7faee4493f220edafd3e56fd15c425a1549b50faa91affbccaf54de406fbe047c70407d1e9f7ef637941539fb30e', - 'id': '14274723388740956065' - }, - /* type: 1 - Register a second signature */ - { - 'type': 1, - 'amount': 0, - 'fee': 500000000, - 'recipientId': null, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'timestamp': 41808966, - 'asset': { - 'signature': { - 'publicKey': '8ccfeb0e05a84124fb8e9932ea5d1744617907ef5b51ffde12e24a805ae992fa' - } - }, - 'signature': '82dc975a49b5fcb19d05b736f7c53978c9973619ef2822e0dfaf0160e1d21a7c5ceb81abb62ebcacfa1c8c3a501035103e252d65fbd5518e38db71f7acc3c20d', - 'id': '16927110199431968159' - }, - /* type: 2 - Register a delegate */ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', - 'timestamp': 43776413, - 'asset': { - 'delegate': { - 'username': 'txp_new_delegate', - 'publicKey': '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' - } - }, - 'signature': '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a', - 'id': '4169182049562816689' - }, - /* type: 3 - Submit votes */ - { - 'type': 3, - 'amount': 0, - 'timestamp': 37943883, - 'fee': 100000000, - 'asset': { - 'votes': [ - '+9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f', - '-141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a' - ] - }, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'senderId': '2737453412992791987L', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '4' - }, - /* type: 4 - Multisignature registration */ - { - 'type': 4, - 'amount': 0, - 'fee': 1500000000, - 'recipientId': null, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'timestamp': 41724474, - 'asset': { - 'multisignature': { - 'min': 2, - 'lifetime': 1, - 'keysgroup': [ - '+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - '+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' - ] - } - }, - 'signature': 'ee0eff648d2f48d72bdbc3f0b4dc57910cf5415a7dd70e8d4c1bfa3ab3cbbe7dd7bac730b0484be744edd6aa136569a37929d749ffe987f872dffa0bd7083d04', - 'id': '16356401289337657230' - }, - /* type: 0 - Transmit funds */ - { - 'type': 0, - 'amount': 300000000, - 'fee': 10000000, - 'timestamp': 37943886, - 'recipientId': '2896019180726908125L', - 'senderId': '2737453412992791987L', - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '6' - }, -]; - -var extraTransaction = { - 'type': 0, - 'amount': 400000000, - 'fee': 10000000, - 'timestamp': 37943890, - 'recipientId': '2896019180726908125L', - 'senderId': '13898484363564790288L', - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'signature': '57bc34c092189e6520b1fcb5b8a1e911d5aed56910ae75d8bbf6145b780dce539949ba86a0ae8d6a33b3a2a68ce8c16eb39b448b4e53f5ca8b04a0da3b438907', - 'id': '8' -}; - -var invalidsTxs = [ - /* type: 0 - Transmit funds account without enough credit*/ - { - 'type': 0, - 'amount': 4400000000, - 'fee': 10000000, - 'recipientId': '2737453412992791987L', - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'timestamp': 42412477, - 'asset': {}, - 'signature': '90e303cb9d547acb680852c8fd583b3c798011e9e01739cd4755f8b4a34607157a9629441e3a2093f46f441de3ed6609080be1e5a2bf13c46b8cfea68d4ada09', - 'id': '5123711709529859173' - }, - /* type: 1 - Register a second signature account without enough credit*/ - { - 'type': 1, - 'amount': 0, - 'fee': 500000000, - 'recipientId': null, - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'timestamp': 42999044, - 'asset': { - 'signature': { - 'publicKey': '8ccfeb0e05a84124fb8e9932ea5d1744617907ef5b51ffde12e24a805ae992fa' - } - }, - 'signature': '30fb1a449dc132a30fa18ad0e905f4702b19dd5199767b8c3a1673173e8905c75a9163980d2c2a06d48faec6a778139cb1fa784a1cbbaa929395675a64231100', - 'id': '7078486003124131749' - }, - [ - /* type: 2 - Register a delegate account without enough credit*/ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9', - 'timestamp': 43775831, - 'asset': { - 'delegate': { - 'username': 'txp_new_delegate', - 'publicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9' - } - }, - 'signature': 'c67bb4f37a2aba0c3e67292ca61fd50064ef3fb32858cbe4b34fa1469ed3978db6b682df609117c1e227156d427bc24f0a3af8bd1ae6ec9194177ad417dd1500', - 'id': '7121061506817701772' - }, - /* type: 2 - Register a delegate that already is delegate*/ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - 'timestamp': 43697153, - 'asset': { - 'delegate': { - 'username': 'txp_test_1', - 'publicKey': 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' - } - }, - 'signature': 'c9441e49228006e9ab9f5f676c49a56f8ec0eb23c539115912cd5b0d48f51c897d01ad2f5abd6bfac92cadbc3704bce076d1c104c63de1a28b247271c5d72601', - 'id': '358375690571860615' - }, - /* type: 2 - Register a delegate account with existing username*/ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'timestamp': 43697153, - 'asset': { - 'delegate': { - 'username': 'txp_test_2', - 'publicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb' - } - }, - 'signature': '3522664cfbe9a5ca3ade309a0c96add1861e29c7f0b3b9aa77177492c69a47f9f7c718dbd415ad49682215826a01579f74d728c6e1bc1c8e808d9ca3a06b8b0c', - 'id': '11660632744648534794' - } - ], - {}, - { - 'type': 4, - 'amount': 0, - 'fee': 1500000000, - 'recipientId': null, - 'senderPublicKey': '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - 'timestamp': 41725704, - 'asset': { - 'multisignature': { - 'min': 2, - 'lifetime': 1, - 'keysgroup': [ - '+684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - '+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' - ] - } - }, - 'signature': '6f3e29e8e4d16f3e808133f6bf73858a3e2a932e19173260a4aaf78041399de67ef505186360a8f11a4b6b471f4f146bb9cbb388e3deb12e19540b8524a8760d', - 'id': '2761953166306398206' - } - /* type: 0 - Transmit funds invalid senderId and recipientId*/ -]; - var testAccounts = [ { account: { @@ -244,6 +29,7 @@ var testAccounts = [ u_balance: 5300000000000000 }, secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', + secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' },{ account: { username: 'txp_test_2', @@ -277,6 +63,53 @@ var testAccounts = [ } ]; +var transactions = [ + /* type: 0 - Transmit funds */ + node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), + /* type: 1 - Register a second signature */ + node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), + /* type: 2 - Register a delegate */ + node.lisk.delegate.createDelegate(testAccounts[3].secret, 'txp_new_delegate'), + /* type: 3 - Submit votes */ + /* type: 4 - Multisignature registration */ +]; + +var invalidsTxs = [ + /* Type: 0 - Transmit funds account without enough credit.*/ + node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000, testAccounts[1].secret), + /* Type: 1 - Register a second signature account without enough credit.*/ + node.lisk.signature.createSignature(testAccounts[1].secret, testAccounts[0].secret2), + /* Type: 2.*/ + [ + /* - Register a delegate account without enough credit.*/ + node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'txp_new_delegate'), + /* - Register a delegate that already is delegate*/ + node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), + /* - Register a delegate account with existing username*/ + node.lisk.delegate.createDelegate(testAccounts[1].secret, testAccounts[1].account.username) + ] +]; + +var hackedTransactions = [ + /* Invalid signature */ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9', + 'timestamp': 43775831, + 'asset': { + 'delegate': { + 'username': 'txp_new_delegate', + 'publicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9' + } + }, + 'signature': '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a', + 'id': '16349767733713562311' + } +]; + // Set spies for logger var debug = sinon.stub(modulesLoader.scope.logger, 'debug'); var info = sinon.stub(modulesLoader.scope.logger, 'info'); @@ -620,7 +453,6 @@ describe('txPool', function () { }); describe('Tx type: 2 - Register a delegate', function () { - var tmpTxInvalidSignature; it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[2], function (err, cbtx) { @@ -663,11 +495,8 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified with invalid signature', function (done) { - tmpTxInvalidSignature = _.cloneDeep(invalidsTxs[2][0]); - tmpTxInvalidSignature.signature = '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a'; - tmpTxInvalidSignature.id = '16349767733713562311'; - txPool.add(tmpTxInvalidSignature, function (err, cbtx) { + txPool.add(hackedTransactions[0], function (err, cbtx) { if (err) { done(err); } @@ -687,7 +516,7 @@ describe('txPool', function () { expect(error.args[1][1]).to.equal('Account is already a delegate'); expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][2].id); expect(error.args[2][1]).to.equal('Username already exists'); - expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidSignature.id); + expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + hackedTransactions[0].id); expect(error.args[3][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 3; poolTotals.ready += 1; @@ -724,8 +553,8 @@ describe('txPool', function () { }); it('should fail when add same transaction with invalid signature to unverified', function (done) { - txPool.add(tmpTxInvalidSignature, function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidSignature.id); + txPool.add(hackedTransactions[0], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + hackedTransactions[0].id); done(); }); }); @@ -789,6 +618,7 @@ describe('txPool', function () { }); it('should fail when add transaction and pool storage is full', function (done) { + var extraTransaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret); txPool.add(extraTransaction, function (err, cbtx) { expect(err).to.equal('Transaction pool is full'); done(); From f0a13dd54dcdd048a67e65f6bd48d0c5f2e07b3c Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Fri, 13 Oct 2017 15:30:21 +0200 Subject: [PATCH 25/86] Test tx type 3 --- test/unit/logic/transactions/pool.js | 122 +++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 7 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 321efc114dd..5be1da338d7 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -64,14 +64,16 @@ var testAccounts = [ ]; var transactions = [ - /* type: 0 - Transmit funds */ + /* Type: 0 - Transmit funds.*/ node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), - /* type: 1 - Register a second signature */ + /* Type: 1 - Register a second signature.*/ node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), - /* type: 2 - Register a delegate */ + /* Type: 2 - Register a delegate.*/ node.lisk.delegate.createDelegate(testAccounts[3].secret, 'txp_new_delegate'), - /* type: 3 - Submit votes */ - /* type: 4 - Multisignature registration */ + /* Type: 3 - Submit votes.*/ + node.lisk.vote.createVote(testAccounts[0].secret, + ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), + /* Type: 4 - Multisignature registration.*/ ]; var invalidsTxs = [ @@ -87,6 +89,15 @@ var invalidsTxs = [ node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), /* - Register a delegate account with existing username*/ node.lisk.delegate.createDelegate(testAccounts[1].secret, testAccounts[1].account.username) + ], + /* Type: 3.*/ + [ + /* - Submit votes from an account without enough credit.*/ + node.lisk.vote.createVote(testAccounts[1].secret, + ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), + /* - Submit votes to an account taht is not a delegate.*/ + node.lisk.vote.createVote(testAccounts[2].secret, + ['+181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c']) ] ]; @@ -169,6 +180,7 @@ describe('txPool', function () { modulesLoader.initModules([ {accounts: require('../../../../modules/accounts')}, + {delegates: require('../../../../modules/delegates')}, ], [ {'transaction': require('../../../../logic/transaction')}, {'account': require('../../../../logic/account')} @@ -179,12 +191,17 @@ describe('txPool', function () { var logicDelegates = new Delegate(modulesLoader.scope.schema); logicDelegates.bind(__modules.accounts); + var logicVote = new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema); + logicVote.bind(__modules.delegates); + __modules.accounts.onBind(__modules); accounts = __modules.accounts; + __modules.delegates.onBind(__modules); + txPool.bind(__modules.accounts); - __trsLogic.attachAssetType(transactionTypes.VOTE, new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema)); + __trsLogic.attachAssetType(transactionTypes.VOTE, logicVote); __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); __trsLogic.attachAssetType(transactionTypes.DELEGATE, logicDelegates); __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature(modulesLoader.scope.schema, modulesLoader.scope.logger)); @@ -587,6 +604,97 @@ describe('txPool', function () { done(); }); }); + + describe('Tx type: 3 - Submit votes', function () { + + it('should be ok when add normal transaction to unverified', function (done) { + txPool.add(transactions[3], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified with not enough LSK', function (done) { + txPool.add(invalidsTxs[3][0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified that votes a non delegate', function (done) { + txPool.add(invalidsTxs[3][1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + if (err) { + done(err); + } + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[3][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[3][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[3][1].id); + expect(error.args[1][1]).to.equal('Delegate not found'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + done(); + }); + }); + + it('should fail when add same normal transaction to unverified', function (done) { + txPool.add(transactions[3], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); + done(); + }); + }); + + it('should fail when add same transaction that votes a non delegate to unverified', function (done) { + txPool.add(invalidsTxs[3][1], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[3][1].id); + done(); + }); + }); + + + it('should be ok when delete normal transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[3]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTxs; + done(); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + }); }); describe('expireTransactions', function () { @@ -598,7 +706,7 @@ describe('txPool', function () { describe('method add', function () { it('should be ok when add transactions to fill pool storage', function (done) { - var trx = transactions.slice(1,transactions.length-2); + var trx = transactions.concat(invalidsTxs); txPool.add(trx, function (err, cbtx) { if (err) { done(err); From 2fab561119292ad1c33bffe8787f64854eb0e8e1 Mon Sep 17 00:00:00 2001 From: lucasisasmendi Date: Tue, 17 Oct 2017 10:13:56 +0200 Subject: [PATCH 26/86] Test tx type 4 skeleton --- logic/transaction.js | 2 + test/unit/logic/transactions/pool.js | 91 +++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/logic/transaction.js b/logic/transaction.js index 63fa8381337..e5bf30cdfe4 100644 --- a/logic/transaction.js +++ b/logic/transaction.js @@ -529,12 +529,14 @@ Transaction.prototype.verify = function (trs, sender, requester, cb) { } // Check confirmed sender balance + /** this check will be done in transaction pool var amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); var senderBalance = this.checkBalance(amount, 'balance', trs, sender); if (senderBalance.exceeded) { return setImmediate(cb, senderBalance.error); } + */ // Check timestamp if (slots.getSlotNumber(trs.timestamp) > slots.getSlotNumber()) { diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 5be1da338d7..7d1292db1f8 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -666,7 +666,6 @@ describe('txPool', function () { }); }); - it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[3]); @@ -695,6 +694,96 @@ describe('txPool', function () { done(); }); }); + + describe('Tx type: 4 - Multisignature registration', function () { + + it('should be ok when add normal transaction to unverified', function (done) { + txPool.add(transactions[4], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified with not enough LSK', function (done) { + txPool.add(invalidsTxs[4][0], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction to unverified that votes a non delegate', function (done) { + txPool.add(invalidsTxs[4][1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + if (err) { + done(err); + } + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[4][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[4][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[4][1].id); + expect(error.args[1][1]).to.equal('Delegate not found'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + done(); + }); + }); + + it('should fail when add same normal transaction to unverified', function (done) { + txPool.add(transactions[3], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); + done(); + }); + }); + + it('should fail when add same transaction that votes a non delegate to unverified', function (done) { + txPool.add(invalidsTxs[4][1], function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[4][1].id); + done(); + }); + }); + + it('should be ok when delete normal transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[4]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTxs; + done(); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + }); }); describe('expireTransactions', function () { From 8a4533037f8e8980f4bb4dff5bc2cda9dba18357 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 18 Oct 2017 15:18:18 +0200 Subject: [PATCH 27/86] Test tx type 4 --- test/unit/logic/transactions/pool.js | 82 ++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 7d1292db1f8..efa7501b710 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -74,6 +74,16 @@ var transactions = [ node.lisk.vote.createVote(testAccounts[0].secret, ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), /* Type: 4 - Multisignature registration.*/ + [ + /* - Create normal multisignature, all accounts in database */ + createMultisignatureSigned (testAccounts[0].secret, null, + ['+' + testAccounts[1].account.publicKey, '+' + testAccounts[2].account.publicKey], + [testAccounts[1].secret, testAccounts[2].secret], 1, 2), + /* - Create multisignature signed with signer account not register in database.*/ + createMultisignatureSigned (testAccounts[2].secret, null, + ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], + ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1) + ] ]; var invalidsTxs = [ @@ -95,9 +105,18 @@ var invalidsTxs = [ /* - Submit votes from an account without enough credit.*/ node.lisk.vote.createVote(testAccounts[1].secret, ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), - /* - Submit votes to an account taht is not a delegate.*/ + /* - Submit votes to an account that is not a delegate.*/ node.lisk.vote.createVote(testAccounts[2].secret, ['+181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c']) + ], + /* Type: 4.*/ + [ + /* - Create multisignature signed from an account without enough credit.*/ + createMultisignatureSigned (testAccounts[1].secret, null, + ['+' + testAccounts[3].account.publicKey,], [testAccounts[3].secret], 1, 1), + /* - Create multisignature signed without.*/ + createMultisignatureSigned (testAccounts[3].secret, null, + ['+' + testAccounts[2].account.publicKey,], [testAccounts[2].secret], 1, 2) ] ]; @@ -143,6 +162,17 @@ function restoreSpiesState () { error.restore(); } +function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { + var multisignatureTransaction = node.lisk.multisignature.createMultisignature(creatorSecret, creatorSecondSecret, keysgroup, min, lifetime); + var signatures = []; + signeersSecrets.forEach(function (secret) { + var sign = node.lisk.multisignature.signTransaction(multisignatureTransaction, secret); + signatures.push(sign); + }); + multisignatureTransaction.signatures = signatures; + return multisignatureTransaction; +} + describe('txPool', function () { var accounts; @@ -181,6 +211,7 @@ describe('txPool', function () { modulesLoader.initModules([ {accounts: require('../../../../modules/accounts')}, {delegates: require('../../../../modules/delegates')}, + {multisignatures: require('../../../../modules/multisignatures')}, ], [ {'transaction': require('../../../../logic/transaction')}, {'account': require('../../../../logic/account')} @@ -194,10 +225,13 @@ describe('txPool', function () { var logicVote = new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema); logicVote.bind(__modules.delegates); + var logicMultisignature = new Multisignature(modulesLoader.scope.schema, modulesLoader.scope.network, __trsLogic, modulesLoader.scope.logger); + __modules.accounts.onBind(__modules); accounts = __modules.accounts; __modules.delegates.onBind(__modules); + __modules.multisignatures.onBind(__modules); txPool.bind(__modules.accounts); @@ -205,7 +239,7 @@ describe('txPool', function () { __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); __trsLogic.attachAssetType(transactionTypes.DELEGATE, logicDelegates); __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature(modulesLoader.scope.schema, modulesLoader.scope.logger)); - __trsLogic.attachAssetType(transactionTypes.MULTI, new Multisignature()); + __trsLogic.attachAssetType(transactionTypes.MULTI, logicMultisignature); done(); }); @@ -698,7 +732,7 @@ describe('txPool', function () { describe('Tx type: 4 - Multisignature registration', function () { it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[4], function (err, cbtx) { + txPool.add(transactions[4][0], function (err, cbtx) { if (err) { done(err); } @@ -706,7 +740,17 @@ describe('txPool', function () { done(); }); }); - + + it('should be ok when add transaction to unverified with not register signer in database', function (done) { + txPool.add(transactions[4][1], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[4][0], function (err, cbtx) { if (err) { @@ -717,7 +761,7 @@ describe('txPool', function () { }); }); - it('should be ok when add transaction to unverified that votes a non delegate', function (done) { + it('should be ok when add transaction to unverified without enough signatures', function (done) { txPool.add(invalidsTxs[4][1], function (err, cbtx) { if (err) { done(err); @@ -735,21 +779,28 @@ describe('txPool', function () { expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[4][0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[4][0].senderId, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[4][1].id); - expect(error.args[1][1]).to.equal('Delegate not found'); + expect(error.args[1][1]).to.equal('Invalid multisignature min. Must be less than or equal to keysgroup size'); poolTotals.invalid += 1; - poolTotals.ready += 1; + poolTotals.ready += 2; done(); }); }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[3], function (err, cbtx) { - expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); + txPool.add(transactions[4][0], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[4][0].id); done(); }); }); - it('should fail when add same transaction that votes a non delegate to unverified', function (done) { + it('should fail when add same transaction with unregister signer to unverified', function (done) { + txPool.add(transactions[4][1], function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + transactions[4][1].id); + done(); + }); + }); + + it('should fail when add same transaction without enough signatures to unverified', function (done) { txPool.add(invalidsTxs[4][1], function (err, cbtx) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[4][1].id); done(); @@ -757,7 +808,16 @@ describe('txPool', function () { }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[4]); + var deletedTx = txPool.delete(transactions[4][0]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when delete transaction without enough signatures from ready', function (done) { + var deletedTx = txPool.delete(transactions[4][1]); expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); From 8dd701da30bbb44fa6da4655ca7eeb2dcc9e1608 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 18 Oct 2017 16:20:02 +0200 Subject: [PATCH 28/86] Adjust data for unverified and ready --- test/unit/logic/transactions/pool.js | 36 +++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index efa7501b710..4c2d55414da 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -855,12 +855,17 @@ describe('txPool', function () { describe('method add', function () { it('should be ok when add transactions to fill pool storage', function (done) { - var trx = transactions.concat(invalidsTxs); - txPool.add(trx, function (err, cbtx) { - if (err) { - done(err); + var txs = []; + invalidsTxs.forEach(function (e) { + if (Array.isArray(e)) { + txs = txs.concat(e); + } else { + txs.push(e); } + }); + txPool.add(txs, function (err, cbtx) { expect(cbtx).to.be.undefined; + expect(err).to.equal('Transaction pool is full'); done(); }); }); @@ -886,7 +891,7 @@ describe('txPool', function () { describe('method delete', function () { it('should be ok when delete a transaction from unverified', function (done) { - var deleteTx = txPool.delete(transactions[0]); + var deleteTx = txPool.delete(invalidsTxs[0]); expect(deleteTx).to.be.an('array').that.is.not.empty; expect(deleteTx.length).to.equal(1); @@ -914,14 +919,19 @@ describe('txPool', function () { describe('ready', function () { describe('method addReady/getReady', function () { - + var txs = []; + transactions.forEach(function (e) { + if (Array.isArray(e)) { + txs = txs.concat(e); + } else { + txs.push(e); + } + }); + it('should be ok when add transactions to ready', function (done) { - txPool.addReady(transactions.slice(0,5), function (err, cbtx) { - if (err) { - done(err); - } + txPool.addReady(txs, function (err, cbtx) { expect(cbtx).to.be.undefined; - poolTotals.ready += transactions.slice(0,5).length; + poolTotals.ready += txs.length; done(); }); }); @@ -932,14 +942,12 @@ describe('txPool', function () { expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); expect(readyTxs[3].fee).to.be.at.least(readyTxs[4].fee); + expect(readyTxs[4].fee).to.be.at.least(readyTxs[5].fee); done(); }); it('should be ok when add type 2 transaction again to ready', function (done) { txPool.addReady(transactions[2], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); From 50c27b04622b495d093a109275d396f9a466b49f Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 20 Oct 2017 15:12:23 +0200 Subject: [PATCH 29/86] Multisignature sign function --- logic/transactions/pool.js | 67 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index d3a58e1c38c..71da861bda8 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -2,6 +2,8 @@ var async = require('async'); var _ = require('lodash'); +var crypto = require('crypto'); + var config = require('../../config.json'); var constants = require('../../helpers/constants.js'); var jobsQueue = require('../../helpers/jobsQueue.js'); @@ -26,10 +28,11 @@ var modules, library, self, __private = {}, pool = {}; * @param {Object} logger */ // Constructor -function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger) { +function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger, ed) { library = { logger: logger, bus: bus, + ed: ed, logic: { transaction: transaction, account, account @@ -181,6 +184,26 @@ __private.addReady = function (transaction, poolList, cb) { return setImmediate(cb); }; +/** + * Crates signature based on multisignature transaction and secret. + * @private + * @param {transaction} transaction + * @param {String} secret + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.createSignature = function (transaction, secret, cb) { + var hash = crypto.createHash('sha256').update(secret, 'utf8').digest(); + var keypair = library.ed.makeKeypair(hash); + var publicKey = keypair.publicKey.toString('hex'); + + if (transaction.asset.multisignature.keysgroup.indexOf('+' + publicKey) === -1) { + return setImmediate(cb, 'Permission to sign transaction denied'); + } + var signature = library.logic.transaction.multisign(keypair, transaction); + return setImmediate(cb, null, signature); +}; + /** * Adds transaction id to invalid pool list. * @param {string} id @@ -539,6 +562,36 @@ TxPool.prototype.addReady = function (transactions, cb) { }); }; +/** + * Creates and adds signature to multisignature transaction. + * @param {String} transactionId transaction id + * @param {String} secret secret + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +TxPool.prototype.addSignature = function (transactionId, secret, cb) { + var multisignatureTransaction = pool.verified.pending.transactions[transactionId]; + + if (multisignatureTransaction === undefined) { + library.logger.error(['Failed to add signature to multisignature. Transaction', transactionId, 'not in pool'].join(' ')); + return setImmediate(cb, 'Transaction not in pool'); + } + + // TODO: replace with checkSignature to reflect API 1.0.18 functionality + __private.createSignature(multisignatureTransaction, secret, function (err, signature) { + if (err) { + return setImmediate(cb, err); + } + if (multisignatureTransaction.signatures.indexOf(signature) !== -1) { + library.logger.error(['Transaction already signed:', transactionId].join(' ')); + return setImmediate(cb, 'Transaction already signed'); + } + + multisignatureTransaction.signatures.push(signature); + return setImmediate(cb); + }); +}; + /** * Deletes transaction from pool list. * @implements {__private.delete} @@ -614,8 +667,16 @@ TxPool.prototype.processPool = function (cb) { // process pool.verified.pending (multisig txs signs), and take care // about moving transactions from `verified.pending` to `verified.ready` async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { - __private.delete(transaction.id, pool.verified.pending); - __private.add(transaction, pool.verified.ready, eachSeriesCb); + // Check multisignatures + if (transaction.type === transactionTypes.MULTI && + Array.isArray(transaction.signatures) && + transaction.signatures.length >= transaction.asset.multisignature.min + ) { + __private.delete(transaction.id, pool.verified.pending); + __private.add(transaction, pool.verified.ready, eachSeriesCb); + } else { + return setImmediate(eachSeriesCb); + } }, function (err) { return setImmediate(seriesCb, err); }); From 5bd9df6aced81b171b3b5f9d05977a25fb297d67 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 20 Oct 2017 16:44:38 +0200 Subject: [PATCH 30/86] Test multisignature sign --- logic/transactions/pool.js | 2 +- test/unit/logic/transactions/pool.js | 113 +++++++++++++++++++++------ 2 files changed, 91 insertions(+), 24 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 71da861bda8..508d3cee20c 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -588,7 +588,7 @@ TxPool.prototype.addSignature = function (transactionId, secret, cb) { } multisignatureTransaction.signatures.push(signature); - return setImmediate(cb); + return setImmediate(cb); }); }; diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 4c2d55414da..6fff70fd67e 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -82,7 +82,10 @@ var transactions = [ /* - Create multisignature signed with signer account not register in database.*/ createMultisignatureSigned (testAccounts[2].secret, null, ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], - ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1) + ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1), + /* - Create multisignature signed without enough signatures.*/ + createMultisignatureSigned (testAccounts[3].secret, null, + ['+' + testAccounts[2].account.publicKey,'+' + testAccounts[1].account.publicKey], [testAccounts[2].secret], 1, 2) ] ]; @@ -113,10 +116,10 @@ var invalidsTxs = [ [ /* - Create multisignature signed from an account without enough credit.*/ createMultisignatureSigned (testAccounts[1].secret, null, - ['+' + testAccounts[3].account.publicKey,], [testAccounts[3].secret], 1, 1), - /* - Create multisignature signed without.*/ + ['+' + testAccounts[3].account.publicKey], [testAccounts[3].secret], 1, 1), + /* - Create multisignature signed with invalid signature.*/ createMultisignatureSigned (testAccounts[3].secret, null, - ['+' + testAccounts[2].account.publicKey,], [testAccounts[2].secret], 1, 2) + ['+' + testAccounts[2].account.publicKey], [testAccounts[1].secret], 1, 1) ] ]; @@ -205,7 +208,8 @@ describe('txPool', function () { __trsLogic, __accountLogic, modulesLoader.scope.bus, - modulesLoader.scope.logger + modulesLoader.scope.logger, + modulesLoader.scope.ed ); modulesLoader.initModules([ @@ -751,6 +755,16 @@ describe('txPool', function () { }); }); + it('should be ok when add transaction to unverified without enough signatures', function (done) { + txPool.add(transactions[4][2], function (err, cbtx) { + if (err) { + done(err); + } + expect(cbtx).to.be.undefined; + done(); + }); + }); + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[4][0], function (err, cbtx) { if (err) { @@ -761,7 +775,7 @@ describe('txPool', function () { }); }); - it('should be ok when add transaction to unverified without enough signatures', function (done) { + it('should be ok when add transaction to unverified with invalid signeer', function (done) { txPool.add(invalidsTxs[4][1], function (err, cbtx) { if (err) { done(err); @@ -779,8 +793,9 @@ describe('txPool', function () { expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[4][0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[4][0].senderId, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[4][1].id); - expect(error.args[1][1]).to.equal('Invalid multisignature min. Must be less than or equal to keysgroup size'); + expect(error.args[1][1]).to.equal('Failed to verify multisignature'); poolTotals.invalid += 1; + poolTotals.pending += 1; poolTotals.ready += 2; done(); }); @@ -816,15 +831,6 @@ describe('txPool', function () { done(); }); - it('should be ok when delete transaction without enough signatures from ready', function (done) { - var deletedTx = txPool.delete(transactions[4][1]); - - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); - poolTotals.ready -= 1; - done(); - }); - it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); @@ -843,6 +849,67 @@ describe('txPool', function () { expect(totals.invalid).to.be.equal(poolTotals.invalid); done(); }); + + describe('Sign multisignature', function () { + + it('should fail when sign transaction with invalid signeer', function (done) { + txPool.addSignature(transactions[4][2].id, testAccounts[0].secret, function (err, cbtx) { + expect(err).to.equal('Permission to sign transaction denied'); + done(); + }); + }); + + it('should be ok when sign pending transaction', function (done) { + txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + expect(err).to.be.undefined; + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should fail when sign same pending transaction again', function (done) { + txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + expect(err).to.equal('Transaction already signed'); + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + expect(error.args.length).to.equal(0); + poolTotals.pending -= 1; + poolTotals.ready += 1; + done(); + }); + }); + + it('should fail when sign transaction that is not in the pool', function (done) { + txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + expect(err).to.equal('Transaction not in pool'); + done(); + }); + }); + + it('should be ok when delete transaction from ready', function (done) { + var deletedTx = txPool.delete(transactions[4][2]); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + }); }); }); @@ -1009,17 +1076,17 @@ describe('txPool', function () { describe('checkBalance', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { - txPool.checkBalance(transactions[5], transactions[5].senderId, function (err, cbBalance) { + txPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { if (err) { done(err); } - expect(cbBalance).to.equal('balance: 52999955.9'); + expect(cbBalance).to.equal('balance: 52999979'); done(); }); }); it('should fail when checked account balance with not enough LSK for transaction', function (done) { - txPool.checkBalance(transactions[6], transactions[6].senderId, function (err, cbBalance) { + txPool.checkBalance(invalidsTxs[0], { address: invalidsTxs[0].senderId }, function (err, cbBalance) { if (err) { expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); done(); @@ -1032,14 +1099,14 @@ describe('txPool', function () { describe('get transaction by id', function () { - it.skip('should be ok when transaction is in unverified list', function (done) { - var transaction = txPool.get(transactions[5].id); - expect(transaction.tx).to.deep.equal(transactions[5]); + it('should be ok when transaction is in unverified list', function (done) { + var transaction = txPool.get(transactions[0].id); + expect(transaction.tx).to.deep.equal(transactions[0]); expect(transaction.status).to.equal('unverified'); done(); }); - it.skip('should be ok when transaction is in pending list', function (done) { + it('should be ok when transaction is in pending list', function (done) { var transaction = txPool.get(transactions[5].id); expect(transaction.tx).to.deep.equal(transactions[5]); expect(transaction.status).to.equal('pending'); From 8513aa815277b8ce248de23d16ee194b4408d90e Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 20 Oct 2017 17:04:37 +0200 Subject: [PATCH 31/86] Delete done(err), adjust spaces --- test/unit/logic/transactions/pool.js | 183 ++++++++------------------- 1 file changed, 54 insertions(+), 129 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 6fff70fd67e..642e48bbf2c 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -263,19 +263,13 @@ describe('txPool', function () { it('should be ok when generate account 1', function (done) { accounts.setAccountAndGet(testAccounts[0].account, function (err, newaccount) { - if (err) { - return done(err); - } expect(newaccount.address).to.equal(testAccounts[0].account.address); done(); }); }); - + it('should be ok when generate account 2', function (done) { accounts.setAccountAndGet(testAccounts[1].account, function (err, newaccount) { - if (err) { - return done(err); - } expect(newaccount.address).to.equal(testAccounts[1].account.address); done(); }); @@ -283,19 +277,13 @@ describe('txPool', function () { it('should be ok when generate account 3', function (done) { accounts.setAccountAndGet(testAccounts[2].account, function (err, newaccount) { - if (err) { - return done(err); - } expect(newaccount.address).to.equal(testAccounts[2].account.address); done(); }); }); - + it('should be ok when generate account 4', function (done) { accounts.setAccountAndGet(testAccounts[3].account, function (err, newaccount) { - if (err) { - return done(err); - } expect(newaccount.address).to.equal(testAccounts[3].account.address); done(); }); @@ -303,7 +291,7 @@ describe('txPool', function () { }); describe('process workers', function () { - + it('should be ok when get pool totals to initialize local counter', function (done) { var totals = txPool.getUsage(); @@ -323,9 +311,6 @@ describe('txPool', function () { it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -333,9 +318,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -346,19 +328,13 @@ describe('txPool', function () { tmpTxInvalidId.id = '01234567890123456789'; txPool.add(tmpTxInvalidId, function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { - if (err) { - done(err); - } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidId.id); @@ -368,7 +344,7 @@ describe('txPool', function () { done(); }); }); - + it('should fail when add same normal transaction to unverified', function (done) { txPool.add(transactions[0], function (err, cbtx) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); @@ -385,7 +361,7 @@ describe('txPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[0]); - + expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); poolTotals.ready -= 1; @@ -394,7 +370,7 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - + expect(invalidTxs).to.equal(1); poolTotals.invalid -= 1; done(); @@ -402,7 +378,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.equal(poolTotals.unverified); expect(totals.pending).to.equal(poolTotals.pending); @@ -411,30 +387,24 @@ describe('txPool', function () { done(); }); }); - + describe('Tx type: 1 - Register a second signature', function () { var invalidTransactionType; it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when add transaction to unverified with invalid transaction type', function (done) { invalidTransactionType = _.cloneDeep(invalidsTxs[0]); invalidTransactionType.id = '12345678901234567890'; @@ -451,9 +421,6 @@ describe('txPool', function () { it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { - if (err) { - done(err); - } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[1].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidTransactionType.id); @@ -480,7 +447,7 @@ describe('txPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[1]); - + expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); poolTotals.ready -= 1; @@ -489,7 +456,7 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - + expect(invalidTxs).to.equal(poolTotals.invalid); poolTotals.invalid -= invalidTxs; done(); @@ -497,7 +464,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); expect(totals.pending).to.be.equal(poolTotals.pending); @@ -511,19 +478,13 @@ describe('txPool', function () { it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[2], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[2][0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -531,9 +492,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified that already is a delegate', function (done) { txPool.add(invalidsTxs[2][1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -541,20 +499,13 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with same username', function (done) { txPool.add(invalidsTxs[2][2], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - - it('should be ok when add transaction to unverified with invalid signature', function (done) { + it('should be ok when add transaction to unverified with invalid signature', function (done) { txPool.add(hackedTransactions[0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -562,9 +513,6 @@ describe('txPool', function () { it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { - if (err) { - done(err); - } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[2][0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[2][0].senderId, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][1].id); @@ -616,7 +564,7 @@ describe('txPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[2]); - + expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); poolTotals.ready -= 1; @@ -625,7 +573,7 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - + expect(invalidTxs).to.equal(poolTotals.invalid); poolTotals.invalid -= invalidTxs; done(); @@ -633,7 +581,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); expect(totals.pending).to.be.equal(poolTotals.pending); @@ -647,19 +595,13 @@ describe('txPool', function () { it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[3], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[3][0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -667,9 +609,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified that votes a non delegate', function (done) { txPool.add(invalidsTxs[3][1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -677,9 +616,6 @@ describe('txPool', function () { it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { - if (err) { - done(err); - } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[3][0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[3][0].senderId, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[3][1].id); @@ -706,7 +642,7 @@ describe('txPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[3]); - + expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); poolTotals.ready -= 1; @@ -715,7 +651,7 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - + expect(invalidTxs).to.equal(poolTotals.invalid); poolTotals.invalid -= invalidTxs; done(); @@ -723,7 +659,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); expect(totals.pending).to.be.equal(poolTotals.pending); @@ -737,9 +673,6 @@ describe('txPool', function () { it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[4][0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -747,9 +680,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with not register signer in database', function (done) { txPool.add(transactions[4][1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -757,9 +687,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified without enough signatures', function (done) { txPool.add(transactions[4][2], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -767,9 +694,6 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with not enough LSK', function (done) { txPool.add(invalidsTxs[4][0], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); @@ -777,19 +701,13 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with invalid signeer', function (done) { txPool.add(invalidsTxs[4][1], function (err, cbtx) { - if (err) { - done(err); - } expect(cbtx).to.be.undefined; done(); }); }); - + it('should be ok when process pool txs', function (done) { txPool.processPool(function (err, cbprPool) { - if (err) { - done(err); - } expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[4][0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[4][0].senderId, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[4][1].id); @@ -824,7 +742,7 @@ describe('txPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTx = txPool.delete(transactions[4][0]); - + expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); poolTotals.ready -= 1; @@ -833,7 +751,7 @@ describe('txPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTxs = txPool.resetInvalidTransactions(); - + expect(invalidTxs).to.equal(poolTotals.invalid); poolTotals.invalid -= invalidTxs; done(); @@ -841,7 +759,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); expect(totals.pending).to.be.equal(poolTotals.pending); @@ -901,7 +819,7 @@ describe('txPool', function () { it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); - + expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); expect(totals.pending).to.be.equal(poolTotals.pending); @@ -983,7 +901,7 @@ describe('txPool', function () { }); }); }); - + describe('ready', function () { describe('method addReady/getReady', function () { var txs = []; @@ -994,7 +912,7 @@ describe('txPool', function () { txs.push(e); } }); - + it('should be ok when add transactions to ready', function (done) { txPool.addReady(txs, function (err, cbtx) { expect(cbtx).to.be.undefined; @@ -1005,6 +923,7 @@ describe('txPool', function () { it('should be ok when get transactions from ready', function (done) { var readyTxs = txPool.getReady(); + expect(readyTxs[0].fee).to.be.at.least(readyTxs[1].fee); expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); @@ -1022,6 +941,7 @@ describe('txPool', function () { it('should be ok when get transactions from ready', function (done) { var readyTxs = txPool.getReady(); + expect(readyTxs[0].receivedAt).to.not.equal(readyTxs[1].receivedAt); expect(readyTxs[1].receivedAt).to.equal(readyTxs[2].receivedAt); expect(readyTxs[2].receivedAt).to.equal(readyTxs[3].receivedAt); @@ -1054,6 +974,7 @@ describe('txPool', function () { it('should be ok when serialize transaction', function (done) { broadcastTx = bson.serialize(transactions[0]); + expect(broadcastTx).that.is.an('Uint8Array'); done(); }); @@ -1068,6 +989,7 @@ describe('txPool', function () { it('should be ok when deserialize transaction', function (done) { broadcastTx = bson.deserialize(broadcastTx); + expect(broadcastTx).to.deep.equal(transactions[0]); done(); }); @@ -1077,9 +999,6 @@ describe('txPool', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { txPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { - if (err) { - done(err); - } expect(cbBalance).to.equal('balance: 52999979'); done(); }); @@ -1087,10 +1006,8 @@ describe('txPool', function () { it('should fail when checked account balance with not enough LSK for transaction', function (done) { txPool.checkBalance(invalidsTxs[0], { address: invalidsTxs[0].senderId }, function (err, cbBalance) { - if (err) { - expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); - done(); - } + expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); + done(); }); }); }); @@ -1101,6 +1018,7 @@ describe('txPool', function () { it('should be ok when transaction is in unverified list', function (done) { var transaction = txPool.get(transactions[0].id); + expect(transaction.tx).to.deep.equal(transactions[0]); expect(transaction.status).to.equal('unverified'); done(); @@ -1108,6 +1026,7 @@ describe('txPool', function () { it('should be ok when transaction is in pending list', function (done) { var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); expect(transaction.status).to.equal('pending'); done(); @@ -1115,6 +1034,7 @@ describe('txPool', function () { it('should be ok when transaction is in ready list', function (done) { var transaction = txPool.get(transactions[5].id); + expect(transaction.tx).to.deep.equal(transactions[5]); expect(transaction.status).to.equal('ready'); done(); @@ -1122,6 +1042,7 @@ describe('txPool', function () { it('should fail when transaction is not in the pool', function (done) { var transaction = txPool.get(transactions[0].id); + expect(transaction.tx).to.be.undefined; expect(transaction.status).to.equal('Transaction not in pool'); done(); @@ -1134,43 +1055,47 @@ describe('txPool', function () { it('should be ok when pool list is unverified', function (done) { var txs = txPool.getAll('unverified', { limit: null}); + expect(txs.length).to.equal(0); done(); }); - + it('should be ok when pool list is pending', function (done) { var txs = txPool.getAll('pending', { limit: null}); + expect(txs.length).to.equal(0); done(); }); - + it('should be ok when pool list is ready', function (done) { var txs = txPool.getAll('ready', { limit: null}); + expect(txs.length).to.equal(5); done(); }); - + it('should fail when filter is invalid', function (done) { var txs = txPool.getAll('unknown', { limit: null}); + expect(txs).to.equal('Invalid filter'); done(); }); }); describe('by id (address) and publicKey', function () { - + it('should be ok when sender account is valid', function (done) { var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); - + expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); expect(txs.ready.length).to.equal(3); done(); }); - + it('should be ok when recipient account is valid', function (done) { var txs = txPool.getAll('recipient_id', { id: '16313739661670634666L' }); - + expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); expect(txs.ready.length).to.equal(1); @@ -1179,16 +1104,16 @@ describe('txPool', function () { it('should be ok when sender publicKey is valid', function (done) { var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - + expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); expect(txs.ready.length).to.equal(3); done(); }); - + it('should be ok when requester publicKey is valid', function (done) { var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - + expect(txs.unverified.length).to.equal(0); expect(txs.pending.length).to.equal(0); expect(txs.ready.length).to.equal(0); From ae040cc599a4ed384f69bdf3a7d68dfbee1398e2 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 23 Oct 2017 12:29:17 +0200 Subject: [PATCH 32/86] Move hardcoded values to constants --- helpers/constants.js | 4 +++- logic/transactions/pool.js | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/helpers/constants.js b/helpers/constants.js index 0816cd52d71..d4e00a3b7de 100644 --- a/helpers/constants.js +++ b/helpers/constants.js @@ -108,7 +108,9 @@ var constants = { minItems: 1, maxItems: 15 } - } + }, + secondsPerHour: 3600, + signatureTransactionTimeOutMultiplier: 8 }; module.exports = constants; diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 508d3cee20c..85a8fa70a07 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -278,9 +278,9 @@ __private.expireTxsFromList = function (poolList, cb) { */ __private.transactionTimeOut = function (transaction) { if (transaction.type === transactionTypes.MULTI) { - return (transaction.asset.multisignature.lifetime * 3600); + return (transaction.asset.multisignature.lifetime * constants.secondsPerHour); } else if (Array.isArray(transaction.signatures)) { - return (constants.unconfirmedTransactionTimeOut * 8); + return (constants.unconfirmedTransactionTimeOut * constants.signatureTransactionTimeOutMultiplier); } else { return (constants.unconfirmedTransactionTimeOut); } @@ -564,6 +564,7 @@ TxPool.prototype.addReady = function (transactions, cb) { /** * Creates and adds signature to multisignature transaction. + * @implements {__private.createSignature} * @param {String} transactionId transaction id * @param {String} secret secret * @param {function} cb - Callback function. From 077e2208318c59bffd47e80e569c6103f78991f3 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 23 Oct 2017 18:11:04 +0200 Subject: [PATCH 33/86] Fix expire transactions --- logic/transactions/pool.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 85a8fa70a07..a078cbedf33 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -259,7 +259,7 @@ __private.expireTxsFromList = function (poolList, cb) { var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); if (seconds > timeOut) { - __private.delete(poolList, transaction.id); + __private.delete(transaction.id, poolList); library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); return setImmediate(eachSeriesCb); } else { @@ -695,14 +695,14 @@ TxPool.prototype.processPool = function (cb) { */ TxPool.prototype.expireTransactions = function (cb) { - async.waterfall([ + async.series([ function (seriesCb) { __private.expireTxsFromList(pool.unverified, seriesCb); }, - function (res, seriesCb) { + function (seriesCb) { __private.expireTxsFromList(pool.verified.pending, seriesCb); }, - function (res, seriesCb) { + function (seriesCb) { __private.expireTxsFromList(pool.verified.ready, seriesCb); } ], function (err) { From 24a958166501a761e47ade4a7ce2da883437af9a Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 23 Oct 2017 18:11:55 +0200 Subject: [PATCH 34/86] Test expire transactions --- test/unit/logic/transactions/pool.js | 160 +++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 11 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 642e48bbf2c..9a7a94b0156 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -10,6 +10,7 @@ var TxPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); var Account = require('../../../../logic/account.js'); var bson = require('../../../../helpers/bson.js'); +var constants = require('../../../../helpers/constants.js'); var transactionTypes = require('../../../../helpers/transactionTypes'); var Vote = require('../../../../logic/vote.js'); @@ -185,7 +186,9 @@ describe('txPool', function () { var poolStorageTxsLimit; before(function (done) { - + constants.unconfirmedTransactionTimeOut = 1; + constants.signatureTransactionTimeOutMultiplier = 1; + constants.secondsPerHour = 1; modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; modulesLoader.scope.config.transactions.poolProcessInterval = 60000000; modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; @@ -475,6 +478,7 @@ describe('txPool', function () { }); describe('Tx type: 2 - Register a delegate', function () { + var invalidSignature; it('should be ok when add normal transaction to unverified', function (done) { txPool.add(transactions[2], function (err, cbtx) { @@ -505,7 +509,9 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified with invalid signature', function (done) { - txPool.add(hackedTransactions[0], function (err, cbtx) { + invalidSignature = _.cloneDeep(hackedTransactions[0]); + + txPool.add(invalidSignature, function (err, cbtx) { expect(cbtx).to.be.undefined; done(); }); @@ -519,7 +525,7 @@ describe('txPool', function () { expect(error.args[1][1]).to.equal('Account is already a delegate'); expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][2].id); expect(error.args[2][1]).to.equal('Username already exists'); - expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + hackedTransactions[0].id); + expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(error.args[3][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 3; poolTotals.ready += 1; @@ -556,8 +562,8 @@ describe('txPool', function () { }); it('should fail when add same transaction with invalid signature to unverified', function (done) { - txPool.add(hackedTransactions[0], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + hackedTransactions[0].id); + txPool.add(invalidSignature, function (err, cbtx) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidSignature.id); done(); }); }); @@ -670,9 +676,13 @@ describe('txPool', function () { }); describe('Tx type: 4 - Multisignature registration', function () { + var notEnoughSignatures; + var completedSignatures; it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[4][0], function (err, cbtx) { + completedSignatures = _.cloneDeep(transactions[4][0]); + + txPool.add(completedSignatures, function (err, cbtx) { expect(cbtx).to.be.undefined; done(); }); @@ -686,7 +696,9 @@ describe('txPool', function () { }); it('should be ok when add transaction to unverified without enough signatures', function (done) { - txPool.add(transactions[4][2], function (err, cbtx) { + notEnoughSignatures = _.cloneDeep(transactions[4][2]); + + txPool.add(notEnoughSignatures, function (err, cbtx) { expect(cbtx).to.be.undefined; done(); }); @@ -720,8 +732,8 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[4][0], function (err, cbtx) { - expect(err).to.equal('Transaction is already in pool: ' + transactions[4][0].id); + txPool.add(completedSignatures, function (err, cbtx) { + expect(err).to.equal('Transaction is already in pool: ' + completedSignatures.id); done(); }); }); @@ -741,7 +753,16 @@ describe('txPool', function () { }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[4][0]); + var deletedTx = txPool.delete(completedSignatures); + + expect(deletedTx.length).to.equal(1); + expect(deletedTx[0]).to.equal('ready'); + poolTotals.ready -= 1; + done(); + }); + + it('should be ok when delete normal transaction without enough signatures to unverified', function (done) { + var deletedTx = txPool.delete(transactions[4][1]); expect(deletedTx.length).to.equal(1); expect(deletedTx[0]).to.equal('ready'); @@ -832,6 +853,123 @@ describe('txPool', function () { }); describe('expireTransactions', function () { + var invalidSignature; + var completedSignatures; + var notEnoughSignatures; + var normalTransaction; + + it('should be ok when add transaction to unverified with invalid signature', function (done) { + invalidSignature = _.cloneDeep(hackedTransactions[0]); + + txPool.add(invalidSignature, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add normal transaction type 4 to unverified', function (done) { + completedSignatures = _.cloneDeep(transactions[4][0]); + + txPool.add(completedSignatures, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { + notEnoughSignatures = _.cloneDeep(transactions[4][2]); + + txPool.add(notEnoughSignatures, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); + expect(error.args[0][1]).to.equal('Failed to verify signature'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + poolTotals.pending += 1; + done(); + }); + }); + + it('should be ok when add normal transaction type 2 to unverified', function (done) { + normalTransaction = _.cloneDeep(transactions[2]); + + txPool.add(normalTransaction, function (err, cbtx) { + expect(cbtx).to.be.undefined; + poolTotals.unverified += 1; + done(); + }); + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); + + it('should be ok when get transaction from unverified list', function (done) { + var transaction = txPool.get(normalTransaction.id); + + expect(transaction.tx).to.deep.equal(normalTransaction); + expect(transaction.status).to.equal('unverified'); + normalTransaction.receivedAt = transaction.tx.receivedAt; + done(); + }); + + it('should be ok when get transaction from pending list', function (done) { + var transaction = txPool.get(notEnoughSignatures.id); + + expect(transaction.tx).to.deep.equal(notEnoughSignatures); + expect(transaction.status).to.equal('pending'); + notEnoughSignatures.receivedAt = transaction.tx.receivedAt; + done(); + }); + + it('should be ok when transaction from ready list', function (done) { + var transaction = txPool.get(completedSignatures.id); + + expect(transaction.tx).to.deep.equal(completedSignatures); + expect(transaction.status).to.equal('ready'); + completedSignatures.receivedAt = transaction.tx.receivedAt; + done(); + }); + + it('should be ok when exprire transactions', function (done) { + setTimeout(function () { + txPool.expireTransactions(function (err, cbprPool) { + expect(info.args.length).to.equal(3); + expect(info.args[0][0]).to.equal(['Expired transaction:', normalTransaction.id, 'received at:', normalTransaction.receivedAt.toUTCString()].join(' ')); + expect(info.args[1][0]).to.equal(['Expired transaction:', notEnoughSignatures.id, 'received at:', notEnoughSignatures.receivedAt.toUTCString()].join(' ')); + expect(info.args[2][0]).to.equal(['Expired transaction:', completedSignatures.id, 'received at:', completedSignatures.receivedAt.toUTCString()].join(' ')); + poolTotals.pending -= 1; + poolTotals.ready -= 1; + poolTotals.unverified -= 1; + done(); + }); + }, 2000); + + }); + + it('should be ok when get pool totals', function (done) { + var totals = txPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(poolTotals.unverified); + expect(totals.pending).to.be.equal(poolTotals.pending); + expect(totals.ready).to.be.equal(poolTotals.ready); + expect(totals.invalid).to.be.equal(poolTotals.invalid); + done(); + }); }); }); @@ -999,7 +1137,7 @@ describe('txPool', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { txPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { - expect(cbBalance).to.equal('balance: 52999979'); + expect(cbBalance).to.equal('balance: 52999994'); done(); }); }); From 2a293faf86de97bb97235906ff6e0cefb5938f03 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 24 Oct 2017 12:19:28 +0200 Subject: [PATCH 35/86] Fix get transactions from pool list --- logic/transactions/pool.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index a078cbedf33..91e43eec03a 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -105,10 +105,16 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE * @return {transaction[]} */ __private.getTxsFromPoolList = function (transactions, limit) { - var txs; + var txs = {}; if (limit) { - txs = Object.keys(transactions).splice(limit); + var i = 1; + for (var key in transactions) { + txs[key] = transactions[key]; + if (++i > limit) { break; } + } + } else { + txs = transactions; } return txs; From 91cf5c9e028d5463b4d327fade6f3b7fd75bd399 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 24 Oct 2017 12:20:18 +0200 Subject: [PATCH 36/86] Test getters --- test/unit/logic/transactions/pool.js | 325 +++++++++++++++++---------- 1 file changed, 210 insertions(+), 115 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 9a7a94b0156..0e46cb25b2c 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -935,7 +935,7 @@ describe('txPool', function () { done(); }); - it('should be ok when transaction from ready list', function (done) { + it('should be ok when get transaction from ready list', function (done) { var transaction = txPool.get(completedSignatures.id); expect(transaction.tx).to.deep.equal(completedSignatures); @@ -960,6 +960,14 @@ describe('txPool', function () { }); + it('should be ok when reset invalid transactions list', function (done) { + var invalidTxs = txPool.resetInvalidTransactions(); + + expect(invalidTxs).to.equal(1); + poolTotals.invalid -= 1; + done(); + }); + it('should be ok when get pool totals', function (done) { var totals = txPool.getUsage(); @@ -973,6 +981,203 @@ describe('txPool', function () { }); }); + describe('getters', function () { + var invalidSignature; + var completedSignatures; + var notEnoughSignatures; + var normalTransaction; + + describe('load transactions to pool', function () { + + it('should be ok when add transaction to unverified with invalid signature', function (done) { + invalidSignature = _.cloneDeep(hackedTransactions[0]); + + txPool.add(invalidSignature, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add normal transaction type 4 to unverified', function (done) { + completedSignatures = _.cloneDeep(transactions[4][0]); + + txPool.add(completedSignatures, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { + notEnoughSignatures = _.cloneDeep(transactions[4][2]); + + txPool.add(notEnoughSignatures, function (err, cbtx) { + expect(cbtx).to.be.undefined; + done(); + }); + }); + + it('should be ok when process pool txs', function (done) { + txPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); + expect(error.args[0][1]).to.equal('Failed to verify signature'); + poolTotals.invalid += 1; + poolTotals.ready += 1; + poolTotals.pending += 1; + done(); + }); + }); + + it('should be ok when add normal transaction type 2 to unverified', function (done) { + normalTransaction = _.cloneDeep(transactions[2]); + + txPool.add(normalTransaction, function (err, cbtx) { + expect(cbtx).to.be.undefined; + poolTotals.unverified += 1; + done(); + }); + }); + + it('should be ok when add normal transaction type 3 to unverified', function (done) { + var normalTransactionT3 = _.cloneDeep(transactions[3]); + normalTransactionT3.requesterPublicKey = '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'; + txPool.add(normalTransactionT3, function (err, cbtx) { + expect(cbtx).to.be.undefined; + poolTotals.unverified += 1; + done(); + }); + }); + }); + + describe('get transaction by id', function () { + + it('should be ok when transaction is in unverified list', function (done) { + var transaction = txPool.get(normalTransaction.id); + + expect(transaction.tx).to.deep.equal(normalTransaction); + expect(transaction.status).to.equal('unverified'); + done(); + }); + + it('should be ok when transaction is in pending list', function (done) { + var transaction = txPool.get(notEnoughSignatures.id); + + expect(transaction.tx).to.deep.equal(notEnoughSignatures); + expect(transaction.status).to.equal('pending'); + done(); + }); + + it('should be ok when transaction is in ready list', function (done) { + var transaction = txPool.get(completedSignatures.id); + + expect(transaction.tx).to.deep.equal(completedSignatures); + expect(transaction.status).to.equal('ready'); + done(); + }); + + it('should fail when transaction is not in the pool', function (done) { + var transaction = txPool.get(transactions[0].id); + + expect(transaction.tx).to.be.undefined; + expect(transaction.status).to.equal('Transaction not in pool'); + done(); + }); + }); + + describe('getAll', function () { + + describe('by pool list', function () { + + it('should be ok when check pool list unverified', function (done) { + var txs = txPool.getAll('unverified', { limit: null }); + + expect(Object.keys(txs).length).to.equal(2); + done(); + }); + + it('should be ok when check pool list unverified with limit', function (done) { + var txs = txPool.getAll('unverified', { limit: 1 }); + + expect(Object.keys(txs).length).to.equal(1); + done(); + }); + + it('should be ok when check pool list pending', function (done) { + var txs = txPool.getAll('pending', { limit: null }); + + expect(Object.keys(txs).length).to.equal(1); + done(); + }); + + it('should be ok when check pool list pending with limit', function (done) { + var txs = txPool.getAll('pending', { limit: 1 }); + + expect(Object.keys(txs).length).to.equal(1); + done(); + }); + + it('should be ok when check pool list ready', function (done) { + var txs = txPool.getAll('ready', { limit: null }); + + expect(Object.keys(txs).length).to.equal(1); + done(); + }); + + it('should be ok when check pool list ready with limit', function (done) { + var txs = txPool.getAll('ready', { limit: 1 }); + + expect(Object.keys(txs).length).to.equal(1); + done(); + }); + + it('should fail when filter is invalid', function (done) { + var txs = txPool.getAll('unknown', { limit: null }); + + expect(txs).to.equal('Invalid filter'); + done(); + }); + }); + + describe('by id (address) and publicKey', function () { + + it('should be ok when sender account is valid', function (done) { + var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); + + expect(txs.unverified.length).to.equal(1); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(1); + done(); + }); + + it('should be ok when recipient account is valid', function (done) { + var txs = txPool.getAll('recipient_id', { id: '2737453412992791987L' }); + + expect(txs.unverified.length).to.equal(1); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should be ok when sender publicKey is valid', function (done) { + var txs = txPool.getAll('sender_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + + expect(txs.unverified.length).to.equal(1); + expect(txs.pending.length).to.equal(1); + expect(txs.ready.length).to.equal(0); + done(); + }); + + it('should be ok when requester publicKey is valid', function (done) { + var txs = txPool.getAll('recipient_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + + expect(txs.unverified.length).to.equal(1); + expect(txs.pending.length).to.equal(0); + expect(txs.ready.length).to.equal(0); + done(); + }); + }); + }); + }); + describe('unverified', function () { describe('method add', function () { @@ -1050,11 +1255,12 @@ describe('txPool', function () { txs.push(e); } }); + txs.pop(); it('should be ok when add transactions to ready', function (done) { txPool.addReady(txs, function (err, cbtx) { expect(cbtx).to.be.undefined; - poolTotals.ready += txs.length; + poolTotals.ready += txs.length -1; done(); }); }); @@ -1093,6 +1299,7 @@ describe('txPool', function () { expect(deleteTx).to.be.an('array').that.is.not.empty; expect(deleteTx.length).to.equal(1); expect(deleteTx[0]).to.equal('ready'); + poolTotals.ready -= 1; done(); }); @@ -1100,8 +1307,7 @@ describe('txPool', function () { var totals = txPool.getUsage(); expect(totals).to.be.an('object'); - expect(totals.ready).to.equal(poolTotals.ready - 1); - poolTotals = totals; + expect(totals.ready).to.equal(poolTotals.ready); done(); }); }); @@ -1149,115 +1355,4 @@ describe('txPool', function () { }); }); }); - - describe('getters', function () { - - describe('get transaction by id', function () { - - it('should be ok when transaction is in unverified list', function (done) { - var transaction = txPool.get(transactions[0].id); - - expect(transaction.tx).to.deep.equal(transactions[0]); - expect(transaction.status).to.equal('unverified'); - done(); - }); - - it('should be ok when transaction is in pending list', function (done) { - var transaction = txPool.get(transactions[5].id); - - expect(transaction.tx).to.deep.equal(transactions[5]); - expect(transaction.status).to.equal('pending'); - done(); - }); - - it('should be ok when transaction is in ready list', function (done) { - var transaction = txPool.get(transactions[5].id); - - expect(transaction.tx).to.deep.equal(transactions[5]); - expect(transaction.status).to.equal('ready'); - done(); - }); - - it('should fail when transaction is not in the pool', function (done) { - var transaction = txPool.get(transactions[0].id); - - expect(transaction.tx).to.be.undefined; - expect(transaction.status).to.equal('Transaction not in pool'); - done(); - }); - }); - - describe('getAll', function () { - - describe('by pool list', function () { - - it('should be ok when pool list is unverified', function (done) { - var txs = txPool.getAll('unverified', { limit: null}); - - expect(txs.length).to.equal(0); - done(); - }); - - it('should be ok when pool list is pending', function (done) { - var txs = txPool.getAll('pending', { limit: null}); - - expect(txs.length).to.equal(0); - done(); - }); - - it('should be ok when pool list is ready', function (done) { - var txs = txPool.getAll('ready', { limit: null}); - - expect(txs.length).to.equal(5); - done(); - }); - - it('should fail when filter is invalid', function (done) { - var txs = txPool.getAll('unknown', { limit: null}); - - expect(txs).to.equal('Invalid filter'); - done(); - }); - }); - - describe('by id (address) and publicKey', function () { - - it('should be ok when sender account is valid', function (done) { - var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(3); - done(); - }); - - it('should be ok when recipient account is valid', function (done) { - var txs = txPool.getAll('recipient_id', { id: '16313739661670634666L' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(1); - done(); - }); - - it('should be ok when sender publicKey is valid', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(3); - done(); - }); - - it('should be ok when requester publicKey is valid', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5' }); - - expect(txs.unverified.length).to.equal(0); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); - done(); - }); - }); - }); - }); }); \ No newline at end of file From 90050b1557cfd9ee7f9857b79013e11333268dd7 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 24 Oct 2017 14:52:42 +0200 Subject: [PATCH 37/86] Rename to standard naming conventions --- logic/transactions/pool.js | 158 ++++---- test/unit/logic/transactions/pool.js | 560 +++++++++++++-------------- 2 files changed, 359 insertions(+), 359 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 91e43eec03a..f43d516667d 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -19,7 +19,7 @@ var modules, library, self, __private = {}, pool = {}; * transaction expiry timer. * @memberof module:transactions * @class - * @classdesc Main TxPool logic. + * @classdesc Main TransactionPool logic. * @implements {processPool} * @param {number} broadcastInterval * @param {number} releaseLimit @@ -28,7 +28,7 @@ var modules, library, self, __private = {}, pool = {}; * @param {Object} logger */ // Constructor -function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger, ed) { +function TransactionPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger, ed) { library = { logger: logger, bus: bus, @@ -43,7 +43,7 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE releaseLimit: releaseLimit, }, transactions: { - poolStorageTxsLimit: poolLimit, + poolStorageTransactionsLimit: poolLimit, poolProcessInterval: poolInterval, poolExpiryInterval: poolExpiryInterval } @@ -51,7 +51,7 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE }; self = this; - self.poolStorageTxsLimit = library.config.transactions.poolStorageTxsLimit; + self.poolStorageTransactionsLimit = library.config.transactions.poolStorageTransactionsLimit; self.poolProcessInterval = library.config.transactions.poolProcessInterval; self.poolExpiryInterval = library.config.transactions.poolExpiryInterval; pool = { @@ -73,7 +73,7 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE }); } - jobsQueue.register('txPoolNextBundle', nextBundle, self.poolProcessInterval); + jobsQueue.register('transactionPoolNextBundle', nextBundle, self.poolProcessInterval); // Transaction expiry timer function nextExpiry (cb) { @@ -85,14 +85,14 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE }); } - jobsQueue.register('txPoolNextExpiry', nextExpiry, self.poolExpiryInterval); + jobsQueue.register('transactionPoolNextExpiry', nextExpiry, self.poolExpiryInterval); // Invalid transactions reset timer function nextReset () { - library.logger.debug(['Cleared invalid txs:', self.resetInvalidTransactions()].join(' ')); + library.logger.debug(['Cleared invalid transactions:', self.resetInvalidTransactions()].join(' ')); } - jobsQueue.register('txPoolNextReset', nextReset, self.poolExpiryInterval * 10); + jobsQueue.register('transactionPoolNextReset', nextReset, self.poolExpiryInterval * 10); } @@ -104,20 +104,20 @@ function TxPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolE * @param {number} limit * @return {transaction[]} */ -__private.getTxsFromPoolList = function (transactions, limit) { - var txs = {}; +__private.getTransactionsFromPoolList = function (transactionsInPool, limit) { + var transactions = {}; if (limit) { var i = 1; - for (var key in transactions) { - txs[key] = transactions[key]; + for (var key in transactionsInPool) { + transactions[key] = transactionsInPool[key]; if (++i > limit) { break; } } } else { - txs = transactions; + transactions = transactionsInPool; } - return txs; + return transactions; }; /** @@ -126,14 +126,14 @@ __private.getTxsFromPoolList = function (transactions, limit) { * @param {Object} filter search criteria * @return {Objetc} transactions by pool list */ -__private.getAllPoolTxsByFilter = function (filter) { - var txs = { +__private.getAllPoolTransactionsByFilter = function (filter) { + var transactions = { unverified: _.filter(pool.unverified.transactions, filter), pending: _.filter(pool.verified.pending.transactions, filter), ready: _.filter(pool.verified.ready.transactions, filter) }; - return txs; + return transactions; }; /** @@ -153,7 +153,7 @@ __private.transactionInPool = function (id) { /** * Adds transactions to pool list. - * Checks if tx is in pool. Checks pool limit. + * Checks if transaction is in pool. Checks pool limit. * @implements {__private.transactionInPool} * @param {transaction} transaction * @param {Object} poolList @@ -161,7 +161,7 @@ __private.transactionInPool = function (id) { * @return {setImmediateCallback} error | cb */ __private.add = function (transaction, poolList, cb) { - if (__private.countTxsPool() >= self.poolStorageTxsLimit) { + if (__private.countTransactionsPool() >= self.poolStorageTransactionsLimit) { return setImmediate(cb, 'Transaction pool is full'); } if (pool.invalid.transactions[transaction.id] !== undefined) { @@ -226,9 +226,9 @@ __private.addInvalid = function (id) { * @return {boolean} true if transaction id is on the list and was deleted */ __private.delete = function (id, poolList) { - var tx = poolList.transactions[id]; + var transaction = poolList.transactions[id]; - if (tx !== undefined) { + if (transaction !== undefined) { delete poolList.transactions[id]; poolList.count--; return true; @@ -240,7 +240,7 @@ __private.delete = function (id, poolList) { * Sums unverified, verified.pending and verified.ready counters. * @return {Number} Total = unverified + pending + ready */ -__private.countTxsPool = function () { +__private.countTransactionsPool = function () { return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; }; @@ -253,7 +253,7 @@ __private.countTxsPool = function () { * @param {function} cb - Callback function * @return {setImmediateCallback} cb|error */ -__private.expireTxsFromList = function (poolList, cb) { +__private.expireTransactionsFromList = function (poolList, cb) { async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { if (!transaction) { return setImmediate(eachSeriesCb); @@ -372,7 +372,7 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { * Bounds input parameters to private variable modules. * @param {Accounts} accounts */ -TxPool.prototype.bind = function (accounts) { +TransactionPool.prototype.bind = function (accounts) { modules = { accounts: accounts, }; @@ -382,7 +382,7 @@ TxPool.prototype.bind = function (accounts) { * Gets invalid, unverified, verified.pending and verified.ready counters. * @return {Object} unverified, pending, ready */ -TxPool.prototype.getUsage = function () { +TransactionPool.prototype.getUsage = function () { return { unverified: pool.unverified.count, pending: pool.verified.pending.count, @@ -395,62 +395,62 @@ TxPool.prototype.getUsage = function () { * Gets transaction based on transaction id. * Checks all pool lists: unverified, pending, ready. * @param {string} id - * @return {Object} tx, status + * @return {Object} transaction, status */ -TxPool.prototype.get = function (id) { - var tx = pool.unverified.transactions[id]; - if (tx !== undefined) { +TransactionPool.prototype.get = function (id) { + var transaction = pool.unverified.transactions[id]; + if (transaction !== undefined) { return { - tx: tx, + transaction: transaction, status: 'unverified' }; } - tx = pool.verified.pending.transactions[id]; - if (tx !== undefined) { + transaction = pool.verified.pending.transactions[id]; + if (transaction !== undefined) { return { - tx: tx, + transaction: transaction, status: 'pending' }; } - tx = pool.verified.ready.transactions[id]; - if (tx !== undefined) { + transaction = pool.verified.ready.transactions[id]; + if (transaction !== undefined) { return { - tx: tx, + transaction: transaction, status: 'ready' }; } return { - tx: undefined, + transaction: undefined, status: 'Transaction not in pool' }; }; /** * Gets all transactions based on limited filters. - * @implements {__private.getTxsFromPoolList} - * @implements {__private.getAllPoolTxsByFilter} + * @implements {__private.getTransactionsFromPoolList} + * @implements {__private.getAllPoolTransactionsByFilter} * @param {string} filter * @param {Object} params * @return {[transaction]} transaction list based on filter. */ -TxPool.prototype.getAll = function (filter, params) { +TransactionPool.prototype.getAll = function (filter, params) { switch (filter) { case 'unverified': - return __private.getTxsFromPoolList(pool.unverified.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.unverified.transactions, params.limit); case 'pending': - return __private.getTxsFromPoolList(pool.verified.pending.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.verified.pending.transactions, params.limit); case 'ready': - return __private.getTxsFromPoolList(pool.verified.ready.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.verified.ready.transactions, params.limit); case 'sender_id': - return __private.getAllPoolTxsByFilter({'senderId': params.id}); + return __private.getAllPoolTransactionsByFilter({'senderId': params.id}); case 'sender_pk': - return __private.getAllPoolTxsByFilter({'senderPublicKey': params.publicKey}); + return __private.getAllPoolTransactionsByFilter({'senderPublicKey': params.publicKey}); case 'recipient_id': - return __private.getAllPoolTxsByFilter({'recipientId': params.id}); + return __private.getAllPoolTransactionsByFilter({'recipientId': params.id}); case 'recipient_pk': - return __private.getAllPoolTxsByFilter({'requesterPublicKey': params.publicKey}); + return __private.getAllPoolTransactionsByFilter({'requesterPublicKey': params.publicKey}); default: return 'Invalid filter'; } @@ -461,7 +461,7 @@ TxPool.prototype.getAll = function (filter, params) { * @param {number} limit * @return {[transaction]} */ -TxPool.prototype.getReady = function (limit) { +TransactionPool.prototype.getReady = function (limit) { var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'asc']); if (limit && limit < r.length) { r.splice(limit); @@ -476,10 +476,10 @@ TxPool.prototype.getReady = function (limit) { * @param {function} cb - Callback function. * @return {setImmediateCallback} err, transactions */ -TxPool.prototype.checkBalance = function (transaction, sender, cb) { +TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { var poolBalance = new bignum('0'); - var paymentTxs; - var receiptTxs; + var paymentTransactions; + var receiptTransactions; library.logic.account.get({ address: sender.address }, 'balance', function (err, account) { if (err) { @@ -487,22 +487,22 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { } // total payments - paymentTxs = self.getAll('sender_id', { id: sender.address }); - if (paymentTxs.ready.length > 0) { - paymentTxs.ready.forEach(function (paymentTx) { - if (paymentTx.amount) { - poolBalance = poolBalance.minus(paymentTx.amount.toString()); + paymentTransactions = self.getAll('sender_id', { id: sender.address }); + if (paymentTransactions.ready.length > 0) { + paymentTransactions.ready.forEach(function (paymentTransaction) { + if (paymentTransaction.amount) { + poolBalance = poolBalance.minus(paymentTransaction.amount.toString()); } - poolBalance = poolBalance.minus(paymentTx.fee.toString()); + poolBalance = poolBalance.minus(paymentTransaction.fee.toString()); }); } // total receipts - receiptTxs = self.getAll('recipient_id', { id: sender.address }); - if (receiptTxs.ready.length > 0) { - receiptTxs.ready.forEach(function (receiptTx) { - if (receiptTx.type === transactionTypes.SEND) { - poolBalance = poolBalance.plus(receiptTx.amount.toString()); + receiptTransactions = self.getAll('recipient_id', { id: sender.address }); + if (receiptTransactions.ready.length > 0) { + receiptTransactions.ready.forEach(function (receiptTransaction) { + if (receiptTransaction.type === transactionTypes.SEND) { + poolBalance = poolBalance.plus(receiptTransaction.amount.toString()); } }); } @@ -535,7 +535,7 @@ TxPool.prototype.checkBalance = function (transaction, sender, cb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -TxPool.prototype.add = function (transactions, cb) { +TransactionPool.prototype.add = function (transactions, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } @@ -554,7 +554,7 @@ TxPool.prototype.add = function (transactions, cb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -TxPool.prototype.addReady = function (transactions, cb) { +TransactionPool.prototype.addReady = function (transactions, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } @@ -576,7 +576,7 @@ TxPool.prototype.addReady = function (transactions, cb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -TxPool.prototype.addSignature = function (transactionId, secret, cb) { +TransactionPool.prototype.addSignature = function (transactionId, secret, cb) { var multisignatureTransaction = pool.verified.pending.transactions[transactionId]; if (multisignatureTransaction === undefined) { @@ -605,7 +605,7 @@ TxPool.prototype.addSignature = function (transactionId, secret, cb) { * @param {transaction} transaction * @return {Array} names of cleared lists */ -TxPool.prototype.delete = function (transaction) { +TransactionPool.prototype.delete = function (transaction) { var clearedList = []; var poolList = ['unverified','pending','ready']; @@ -616,7 +616,7 @@ TxPool.prototype.delete = function (transaction) { }); if (clearedList.length > 0) { if (clearedList.length > 1) { - library.logger.debug(['Cleared duplicated tx in pool list:', clearedList, 'txid:', transaction.id].join(' ')); + library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transactionid:', transaction.id].join(' ')); } } return clearedList; @@ -624,7 +624,7 @@ TxPool.prototype.delete = function (transaction) { /** * Pulls transactions from unverified, perform verifications and if successful - * push to either verified.pending (when tx is multisign or timestamp is in + * push to either verified.pending (when transaction is multisign or timestamp is in * future) or verified.ready otherwise. * @implements {__private.delete} * @implements {processVerifyTransaction} @@ -632,7 +632,7 @@ TxPool.prototype.delete = function (transaction) { * @param {function} cb * @return {setImmediateCallback} err | cb */ -TxPool.prototype.processPool = function (cb) { +TransactionPool.prototype.processPool = function (cb) { async.series({ processUnverified: function (seriesCb) { if (pool.unverified.count === 0) { @@ -671,7 +671,7 @@ TxPool.prototype.processPool = function (cb) { return setImmediate(seriesCb); } - // process pool.verified.pending (multisig txs signs), and take care + // process pool.verified.pending (multisig transactions signs), and take care // about moving transactions from `verified.pending` to `verified.ready` async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { // Check multisignatures @@ -695,21 +695,21 @@ TxPool.prototype.processPool = function (cb) { /** * Expires transactions. - * @implements {__private.expireTxsFromList} + * @implements {__private.expireTransactionsFromList} * @param {function} cb - Callback function. * @return {setImmediateCallback} error, cb */ -TxPool.prototype.expireTransactions = function (cb) { +TransactionPool.prototype.expireTransactions = function (cb) { async.series([ function (seriesCb) { - __private.expireTxsFromList(pool.unverified, seriesCb); + __private.expireTransactionsFromList(pool.unverified, seriesCb); }, function (seriesCb) { - __private.expireTxsFromList(pool.verified.pending, seriesCb); + __private.expireTransactionsFromList(pool.verified.pending, seriesCb); }, function (seriesCb) { - __private.expireTxsFromList(pool.verified.ready, seriesCb); + __private.expireTransactionsFromList(pool.verified.ready, seriesCb); } ], function (err) { return setImmediate(cb, err); @@ -719,11 +719,11 @@ TxPool.prototype.expireTransactions = function (cb) { /** * Reset invalid transactions. */ -TxPool.prototype.resetInvalidTransactions = function () { +TransactionPool.prototype.resetInvalidTransactions = function () { var counter = 0; - for (var tx in pool.invalid.transactions) { - delete pool.invalid.transactions[tx]; + for (var transaction in pool.invalid.transactions) { + delete pool.invalid.transactions[transaction]; counter++; } pool.invalid.count = 0; @@ -731,4 +731,4 @@ TxPool.prototype.resetInvalidTransactions = function () { }; // Export -module.exports = TxPool; \ No newline at end of file +module.exports = TransactionPool; diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 0e46cb25b2c..ac95bec4f8b 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -6,7 +6,7 @@ var _ = require('lodash'); var node = require('../../../node'); var modulesLoader = require('../../../common/initModule').modulesLoader; -var TxPool = require('../../../../logic/transactions/pool.js'); +var TransactionPool = require('../../../../logic/transactions/pool.js'); var Transaction = require('../../../../logic/transaction.js'); var Account = require('../../../../logic/account.js'); var bson = require('../../../../helpers/bson.js'); @@ -22,7 +22,7 @@ var Multisignature = require('../../../../logic/multisignature.js'); var testAccounts = [ { account: { - username: 'txp_test_1', + username: 'tpool_test_1', isDelegate: 1, address: '2737453412992791987L', publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', @@ -33,7 +33,7 @@ var testAccounts = [ secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' },{ account: { - username: 'txp_test_2', + username: 'tpool_test_2', isDelegate: 0, address: '2896019180726908125L', publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', @@ -43,7 +43,7 @@ var testAccounts = [ secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', },{ account: { - username: 'txp_test_3', + username: 'tpool_test_3', isDelegate: 0, address: '15240249857307028085L', publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', @@ -53,7 +53,7 @@ var testAccounts = [ secret: 'song gather until exercise explain utility walk choice garbage cross route develop', },{ account: { - username: 'txp_test_4', + username: 'tpool_test_4', isDelegate: 0, address: '13898484363564790288L', publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', @@ -70,7 +70,7 @@ var transactions = [ /* Type: 1 - Register a second signature.*/ node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), /* Type: 2 - Register a delegate.*/ - node.lisk.delegate.createDelegate(testAccounts[3].secret, 'txp_new_delegate'), + node.lisk.delegate.createDelegate(testAccounts[3].secret, 'tpool_new_delegate'), /* Type: 3 - Submit votes.*/ node.lisk.vote.createVote(testAccounts[0].secret, ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), @@ -90,7 +90,7 @@ var transactions = [ ] ]; -var invalidsTxs = [ +var invalidsTransactions = [ /* Type: 0 - Transmit funds account without enough credit.*/ node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000, testAccounts[1].secret), /* Type: 1 - Register a second signature account without enough credit.*/ @@ -98,7 +98,7 @@ var invalidsTxs = [ /* Type: 2.*/ [ /* - Register a delegate account without enough credit.*/ - node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'txp_new_delegate'), + node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'tpool_new_delegate'), /* - Register a delegate that already is delegate*/ node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), /* - Register a delegate account with existing username*/ @@ -177,19 +177,19 @@ function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgro return multisignatureTransaction; } -describe('txPool', function () { +describe('transactionPool', function () { var accounts; - var txPool; + var transactionPool; var poolTotals; - var txReady; - var poolStorageTxsLimit; + var transactionReady; + var poolStorageTransactionsLimit; before(function (done) { constants.unconfirmedTransactionTimeOut = 1; constants.signatureTransactionTimeOutMultiplier = 1; constants.secondsPerHour = 1; - modulesLoader.scope.config.transactions.poolStorageTxsLimit = 6; + modulesLoader.scope.config.transactions.poolStorageTransactionsLimit = 6; modulesLoader.scope.config.transactions.poolProcessInterval = 60000000; modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; @@ -201,11 +201,11 @@ describe('txPool', function () { if (err) { return done(err); } - poolStorageTxsLimit = modulesLoader.scope.config.transactions.poolStorageTxsLimit; - txPool = new TxPool( + poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.poolStorageTransactionsLimit; + transactionPool = new TransactionPool( modulesLoader.scope.config.broadcasts.broadcastInterval, modulesLoader.scope.config.broadcasts.releaseLimit, - modulesLoader.scope.config.transactions.poolStorageTxsLimit, + modulesLoader.scope.config.transactions.poolStorageTransactionsLimit, modulesLoader.scope.config.transactions.poolProcessInterval, modulesLoader.scope.config.transactions.poolExpiryInterval, __trsLogic, @@ -240,7 +240,7 @@ describe('txPool', function () { __modules.delegates.onBind(__modules); __modules.multisignatures.onBind(__modules); - txPool.bind(__modules.accounts); + transactionPool.bind(__modules.accounts); __trsLogic.attachAssetType(transactionTypes.VOTE, logicVote); __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); @@ -296,7 +296,7 @@ describe('txPool', function () { describe('process workers', function () { it('should be ok when get pool totals to initialize local counter', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.a('number'); @@ -309,38 +309,38 @@ describe('txPool', function () { describe('processPool', function () { - describe('Tx type: 0 - Transmit funds', function () { - var tmpTxInvalidId; + describe('Transaction type: 0 - Transmit funds', function () { + var tmpTransactionInvalidId; it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[0], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions[0], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[0], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[0], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with invalid transaction id', function (done) { - tmpTxInvalidId = _.cloneDeep(invalidsTxs[0]); - tmpTxInvalidId.id = '01234567890123456789'; + tmpTransactionInvalidId = _.cloneDeep(invalidsTransactions[0]); + tmpTransactionInvalidId.id = '01234567890123456789'; - txPool.add(tmpTxInvalidId, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(tmpTransactionInvalidId, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[0].id); + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[0].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTxInvalidId.id); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTransactionInvalidId.id); expect(error.args[1][1]).to.equal('Invalid transaction id'); poolTotals.invalid += 1; poolTotals.ready += 1; @@ -349,38 +349,38 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[0], function (err, cbtx) { + transactionPool.add(transactions[0], function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); done(); }); }); it('should fail when add same transaction with invalid id to unverified', function (done) { - txPool.add(tmpTxInvalidId, function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTxInvalidId.id); + transactionPool.add(tmpTransactionInvalidId, function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTransactionInvalidId.id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[0]); + var deletedTransaction = transactionPool.delete(transactions[0]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(1); + expect(invalidTransactions).to.equal(1); poolTotals.invalid -= 1; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.equal(poolTotals.unverified); @@ -391,40 +391,40 @@ describe('txPool', function () { }); }); - describe('Tx type: 1 - Register a second signature', function () { + describe('Transaction type: 1 - Register a second signature', function () { var invalidTransactionType; it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions[1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with invalid transaction type', function (done) { - invalidTransactionType = _.cloneDeep(invalidsTxs[0]); + invalidTransactionType = _.cloneDeep(invalidsTransactions[0]); invalidTransactionType.id = '12345678901234567890'; invalidTransactionType.type = 99; - txPool.add(invalidTransactionType, function (err, cbtx) { + transactionPool.add(invalidTransactionType, function (err, cbtransaction) { if (err) { done(err); } - expect(cbtx).to.be.undefined; + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[1].id); + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[1].id); expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0'].join(' ')); expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidTransactionType.id); expect(error.args[1][1]).to.equal(['Unknown transaction type', invalidTransactionType.type].join(' ')); @@ -435,38 +435,38 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[1], function (err, cbtx) { + transactionPool.add(transactions[1], function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); done(); }); }); it('should fail when add same transaction with invalid transaction type to unverified', function (done) { - txPool.add(invalidTransactionType, function (err, cbtx) { + transactionPool.add(invalidTransactionType, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidTransactionType.id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[1]); + var deletedTransaction = transactionPool.delete(transactions[1]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(poolTotals.invalid); - poolTotals.invalid -= invalidTxs; + expect(invalidTransactions).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTransactions; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -477,33 +477,33 @@ describe('txPool', function () { }); }); - describe('Tx type: 2 - Register a delegate', function () { + describe('Transaction type: 2 - Register a delegate', function () { var invalidSignature; it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[2], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions[2], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[2][0], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[2][0], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that already is a delegate', function (done) { - txPool.add(invalidsTxs[2][1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with same username', function (done) { - txPool.add(invalidsTxs[2][2], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[2][2], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -511,19 +511,19 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - txPool.add(invalidSignature, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidSignature, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[2][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[2][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][1].id); + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[2][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[2][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][1].id); expect(error.args[1][1]).to.equal('Account is already a delegate'); - expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[2][2].id); + expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][2].id); expect(error.args[2][1]).to.equal('Username already exists'); expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(error.args[3][1]).to.equal('Failed to verify signature'); @@ -534,59 +534,59 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[2], function (err, cbtx) { + transactionPool.add(transactions[2], function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - txPool.add(invalidsTxs[2][1], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][1].id); + transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - txPool.add(invalidsTxs[2][1], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][1].id); + transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with same username to unverified', function (done) { - txPool.add(invalidsTxs[2][2], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[2][2].id); + transactionPool.add(invalidsTransactions[2][2], function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][2].id); done(); }); }); it('should fail when add same transaction with invalid signature to unverified', function (done) { - txPool.add(invalidSignature, function (err, cbtx) { + transactionPool.add(invalidSignature, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidSignature.id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[2]); + var deletedTransaction = transactionPool.delete(transactions[2]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(poolTotals.invalid); - poolTotals.invalid -= invalidTxs; + expect(invalidTransactions).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTransactions; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -597,34 +597,34 @@ describe('txPool', function () { }); }); - describe('Tx type: 3 - Submit votes', function () { + describe('Transaction type: 3 - Submit votes', function () { it('should be ok when add normal transaction to unverified', function (done) { - txPool.add(transactions[3], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions[3], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[3][0], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[3][0], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that votes a non delegate', function (done) { - txPool.add(invalidsTxs[3][1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[3][1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[3][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[3][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[3][1].id); + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[3][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[3][1].id); expect(error.args[1][1]).to.equal('Delegate not found'); poolTotals.invalid += 1; poolTotals.ready += 1; @@ -633,38 +633,38 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(transactions[3], function (err, cbtx) { + transactionPool.add(transactions[3], function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); done(); }); }); it('should fail when add same transaction that votes a non delegate to unverified', function (done) { - txPool.add(invalidsTxs[3][1], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[3][1].id); + transactionPool.add(invalidsTransactions[3][1], function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[3][1].id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[3]); + var deletedTransaction = transactionPool.delete(transactions[3]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(poolTotals.invalid); - poolTotals.invalid -= invalidTxs; + expect(invalidTransactions).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTransactions; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -675,22 +675,22 @@ describe('txPool', function () { }); }); - describe('Tx type: 4 - Multisignature registration', function () { + describe('Transaction type: 4 - Multisignature registration', function () { var notEnoughSignatures; var completedSignatures; it('should be ok when add normal transaction to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - txPool.add(completedSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(completedSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not register signer in database', function (done) { - txPool.add(transactions[4][1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions[4][1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -698,31 +698,31 @@ describe('txPool', function () { it('should be ok when add transaction to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - txPool.add(notEnoughSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - txPool.add(invalidsTxs[4][0], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[4][0], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with invalid signeer', function (done) { - txPool.add(invalidsTxs[4][1], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidsTransactions[4][1], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTxs[4][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTxs[4][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTxs[4][1].id); + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { + expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[4][0].id); + expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0'].join(' ')); + expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[4][1].id); expect(error.args[1][1]).to.equal('Failed to verify multisignature'); poolTotals.invalid += 1; poolTotals.pending += 1; @@ -732,54 +732,54 @@ describe('txPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - txPool.add(completedSignatures, function (err, cbtx) { + transactionPool.add(completedSignatures, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + completedSignatures.id); done(); }); }); it('should fail when add same transaction with unregister signer to unverified', function (done) { - txPool.add(transactions[4][1], function (err, cbtx) { + transactionPool.add(transactions[4][1], function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[4][1].id); done(); }); }); it('should fail when add same transaction without enough signatures to unverified', function (done) { - txPool.add(invalidsTxs[4][1], function (err, cbtx) { - expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTxs[4][1].id); + transactionPool.add(invalidsTransactions[4][1], function (err, cbtransaction) { + expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[4][1].id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTx = txPool.delete(completedSignatures); + var deletedTransaction = transactionPool.delete(completedSignatures); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when delete normal transaction without enough signatures to unverified', function (done) { - var deletedTx = txPool.delete(transactions[4][1]); + var deletedTransaction = transactionPool.delete(transactions[4][1]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(poolTotals.invalid); - poolTotals.invalid -= invalidTxs; + expect(invalidTransactions).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTransactions; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -792,29 +792,29 @@ describe('txPool', function () { describe('Sign multisignature', function () { it('should fail when sign transaction with invalid signeer', function (done) { - txPool.addSignature(transactions[4][2].id, testAccounts[0].secret, function (err, cbtx) { + transactionPool.addSignature(transactions[4][2].id, testAccounts[0].secret, function (err, cbtransaction) { expect(err).to.equal('Permission to sign transaction denied'); done(); }); }); it('should be ok when sign pending transaction', function (done) { - txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.be.undefined; - expect(cbtx).to.be.undefined; + expect(cbtransaction).to.be.undefined; done(); }); }); it('should fail when sign same pending transaction again', function (done) { - txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.equal('Transaction already signed'); done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { expect(error.args.length).to.equal(0); poolTotals.pending -= 1; poolTotals.ready += 1; @@ -823,23 +823,23 @@ describe('txPool', function () { }); it('should fail when sign transaction that is not in the pool', function (done) { - txPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtx) { + transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.equal('Transaction not in pool'); done(); }); }); it('should be ok when delete transaction from ready', function (done) { - var deletedTx = txPool.delete(transactions[4][2]); + var deletedTransaction = transactionPool.delete(transactions[4][2]); - expect(deletedTx.length).to.equal(1); - expect(deletedTx[0]).to.equal('ready'); + expect(deletedTransaction.length).to.equal(1); + expect(deletedTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -861,8 +861,8 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - txPool.add(invalidSignature, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidSignature, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -870,8 +870,8 @@ describe('txPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - txPool.add(completedSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(completedSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -879,14 +879,14 @@ describe('txPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - txPool.add(notEnoughSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; @@ -899,15 +899,15 @@ describe('txPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - txPool.add(normalTransaction, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(normalTransaction, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); }); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -918,35 +918,35 @@ describe('txPool', function () { }); it('should be ok when get transaction from unverified list', function (done) { - var transaction = txPool.get(normalTransaction.id); + var transaction = transactionPool.get(normalTransaction.id); - expect(transaction.tx).to.deep.equal(normalTransaction); + expect(transaction.transaction).to.deep.equal(normalTransaction); expect(transaction.status).to.equal('unverified'); - normalTransaction.receivedAt = transaction.tx.receivedAt; + normalTransaction.receivedAt = transaction.transaction.receivedAt; done(); }); it('should be ok when get transaction from pending list', function (done) { - var transaction = txPool.get(notEnoughSignatures.id); + var transaction = transactionPool.get(notEnoughSignatures.id); - expect(transaction.tx).to.deep.equal(notEnoughSignatures); + expect(transaction.transaction).to.deep.equal(notEnoughSignatures); expect(transaction.status).to.equal('pending'); - notEnoughSignatures.receivedAt = transaction.tx.receivedAt; + notEnoughSignatures.receivedAt = transaction.transaction.receivedAt; done(); }); it('should be ok when get transaction from ready list', function (done) { - var transaction = txPool.get(completedSignatures.id); + var transaction = transactionPool.get(completedSignatures.id); - expect(transaction.tx).to.deep.equal(completedSignatures); + expect(transaction.transaction).to.deep.equal(completedSignatures); expect(transaction.status).to.equal('ready'); - completedSignatures.receivedAt = transaction.tx.receivedAt; + completedSignatures.receivedAt = transaction.transaction.receivedAt; done(); }); it('should be ok when exprire transactions', function (done) { setTimeout(function () { - txPool.expireTransactions(function (err, cbprPool) { + transactionPool.expireTransactions(function (err, cbprPool) { expect(info.args.length).to.equal(3); expect(info.args[0][0]).to.equal(['Expired transaction:', normalTransaction.id, 'received at:', normalTransaction.receivedAt.toUTCString()].join(' ')); expect(info.args[1][0]).to.equal(['Expired transaction:', notEnoughSignatures.id, 'received at:', notEnoughSignatures.receivedAt.toUTCString()].join(' ')); @@ -961,15 +961,15 @@ describe('txPool', function () { }); it('should be ok when reset invalid transactions list', function (done) { - var invalidTxs = txPool.resetInvalidTransactions(); + var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTxs).to.equal(1); + expect(invalidTransactions).to.equal(1); poolTotals.invalid -= 1; done(); }); it('should be ok when get pool totals', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.be.equal(poolTotals.unverified); @@ -992,8 +992,8 @@ describe('txPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - txPool.add(invalidSignature, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(invalidSignature, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -1001,8 +1001,8 @@ describe('txPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - txPool.add(completedSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(completedSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); @@ -1010,14 +1010,14 @@ describe('txPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - txPool.add(notEnoughSignatures, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool txs', function (done) { - txPool.processPool(function (err, cbprPool) { + it('should be ok when process pool transactions', function (done) { + transactionPool.processPool(function (err, cbprPool) { expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; @@ -1030,8 +1030,8 @@ describe('txPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - txPool.add(normalTransaction, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(normalTransaction, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); }); @@ -1040,8 +1040,8 @@ describe('txPool', function () { it('should be ok when add normal transaction type 3 to unverified', function (done) { var normalTransactionT3 = _.cloneDeep(transactions[3]); normalTransactionT3.requesterPublicKey = '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'; - txPool.add(normalTransactionT3, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(normalTransactionT3, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); }); @@ -1051,33 +1051,33 @@ describe('txPool', function () { describe('get transaction by id', function () { it('should be ok when transaction is in unverified list', function (done) { - var transaction = txPool.get(normalTransaction.id); + var transaction = transactionPool.get(normalTransaction.id); - expect(transaction.tx).to.deep.equal(normalTransaction); + expect(transaction.transaction).to.deep.equal(normalTransaction); expect(transaction.status).to.equal('unverified'); done(); }); it('should be ok when transaction is in pending list', function (done) { - var transaction = txPool.get(notEnoughSignatures.id); + var transaction = transactionPool.get(notEnoughSignatures.id); - expect(transaction.tx).to.deep.equal(notEnoughSignatures); + expect(transaction.transaction).to.deep.equal(notEnoughSignatures); expect(transaction.status).to.equal('pending'); done(); }); it('should be ok when transaction is in ready list', function (done) { - var transaction = txPool.get(completedSignatures.id); + var transaction = transactionPool.get(completedSignatures.id); - expect(transaction.tx).to.deep.equal(completedSignatures); + expect(transaction.transaction).to.deep.equal(completedSignatures); expect(transaction.status).to.equal('ready'); done(); }); it('should fail when transaction is not in the pool', function (done) { - var transaction = txPool.get(transactions[0].id); + var transaction = transactionPool.get(transactions[0].id); - expect(transaction.tx).to.be.undefined; + expect(transaction.transaction).to.be.undefined; expect(transaction.status).to.equal('Transaction not in pool'); done(); }); @@ -1088,51 +1088,51 @@ describe('txPool', function () { describe('by pool list', function () { it('should be ok when check pool list unverified', function (done) { - var txs = txPool.getAll('unverified', { limit: null }); + var transactions = transactionPool.getAll('unverified', { limit: null }); - expect(Object.keys(txs).length).to.equal(2); + expect(Object.keys(transactions).length).to.equal(2); done(); }); it('should be ok when check pool list unverified with limit', function (done) { - var txs = txPool.getAll('unverified', { limit: 1 }); + var transactions = transactionPool.getAll('unverified', { limit: 1 }); - expect(Object.keys(txs).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list pending', function (done) { - var txs = txPool.getAll('pending', { limit: null }); + var transactions = transactionPool.getAll('pending', { limit: null }); - expect(Object.keys(txs).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list pending with limit', function (done) { - var txs = txPool.getAll('pending', { limit: 1 }); + var transactions = transactionPool.getAll('pending', { limit: 1 }); - expect(Object.keys(txs).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list ready', function (done) { - var txs = txPool.getAll('ready', { limit: null }); + var transactions = transactionPool.getAll('ready', { limit: null }); - expect(Object.keys(txs).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list ready with limit', function (done) { - var txs = txPool.getAll('ready', { limit: 1 }); + var transactions = transactionPool.getAll('ready', { limit: 1 }); - expect(Object.keys(txs).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should fail when filter is invalid', function (done) { - var txs = txPool.getAll('unknown', { limit: null }); + var transactions = transactionPool.getAll('unknown', { limit: null }); - expect(txs).to.equal('Invalid filter'); + expect(transactions).to.equal('Invalid filter'); done(); }); }); @@ -1140,38 +1140,38 @@ describe('txPool', function () { describe('by id (address) and publicKey', function () { it('should be ok when sender account is valid', function (done) { - var txs = txPool.getAll('sender_id', { id: '2737453412992791987L' }); + var transactions = transactionPool.getAll('sender_id', { id: '2737453412992791987L' }); - expect(txs.unverified.length).to.equal(1); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(1); + expect(transactions.unverified.length).to.equal(1); + expect(transactions.pending.length).to.equal(0); + expect(transactions.ready.length).to.equal(1); done(); }); it('should be ok when recipient account is valid', function (done) { - var txs = txPool.getAll('recipient_id', { id: '2737453412992791987L' }); + var transactions = transactionPool.getAll('recipient_id', { id: '2737453412992791987L' }); - expect(txs.unverified.length).to.equal(1); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); + expect(transactions.unverified.length).to.equal(1); + expect(transactions.pending.length).to.equal(0); + expect(transactions.ready.length).to.equal(0); done(); }); it('should be ok when sender publicKey is valid', function (done) { - var txs = txPool.getAll('sender_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + var transactions = transactionPool.getAll('sender_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); - expect(txs.unverified.length).to.equal(1); - expect(txs.pending.length).to.equal(1); - expect(txs.ready.length).to.equal(0); + expect(transactions.unverified.length).to.equal(1); + expect(transactions.pending.length).to.equal(1); + expect(transactions.ready.length).to.equal(0); done(); }); it('should be ok when requester publicKey is valid', function (done) { - var txs = txPool.getAll('recipient_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + var transactions = transactionPool.getAll('recipient_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); - expect(txs.unverified.length).to.equal(1); - expect(txs.pending.length).to.equal(0); - expect(txs.ready.length).to.equal(0); + expect(transactions.unverified.length).to.equal(1); + expect(transactions.pending.length).to.equal(0); + expect(transactions.ready.length).to.equal(0); done(); }); }); @@ -1183,33 +1183,33 @@ describe('txPool', function () { describe('method add', function () { it('should be ok when add transactions to fill pool storage', function (done) { - var txs = []; - invalidsTxs.forEach(function (e) { + var transactions = []; + invalidsTransactions.forEach(function (e) { if (Array.isArray(e)) { - txs = txs.concat(e); + transactions = transactions.concat(e); } else { - txs.push(e); + transactions.push(e); } }); - txPool.add(txs, function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.add(transactions, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; expect(err).to.equal('Transaction pool is full'); done(); }); }); it('should be ok when pool totals are equal to pool storage limit', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); var currentStorage = totals.unverified + totals.pending + totals.ready; expect(totals).to.be.an('object'); - expect(currentStorage).to.equal(poolStorageTxsLimit); + expect(currentStorage).to.equal(poolStorageTransactionsLimit); poolTotals = totals; done(); }); it('should fail when add transaction and pool storage is full', function (done) { var extraTransaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret); - txPool.add(extraTransaction, function (err, cbtx) { + transactionPool.add(extraTransaction, function (err, cbtransaction) { expect(err).to.equal('Transaction pool is full'); done(); }); @@ -1219,16 +1219,16 @@ describe('txPool', function () { describe('method delete', function () { it('should be ok when delete a transaction from unverified', function (done) { - var deleteTx = txPool.delete(invalidsTxs[0]); + var deleteTransaction = transactionPool.delete(invalidsTransactions[0]); - expect(deleteTx).to.be.an('array').that.is.not.empty; - expect(deleteTx.length).to.equal(1); - expect(deleteTx[0]).to.equal('unverified'); + expect(deleteTransaction).to.be.an('array').that.is.not.empty; + expect(deleteTransaction.length).to.equal(1); + expect(deleteTransaction[0]).to.equal('unverified'); done(); }); it('should be ok when check unverified value decreased in 1', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.unverified).to.equal(poolTotals.unverified - 1); @@ -1237,9 +1237,9 @@ describe('txPool', function () { }); it('should fail when delete transaction that is not in pool', function (done) { - var deleteTx = txPool.delete(transactions[0]); + var deleteTransaction = transactionPool.delete(transactions[0]); - expect(deleteTx).to.be.an('array').that.is.empty; + expect(deleteTransaction).to.be.an('array').that.is.empty; done(); }); }); @@ -1247,64 +1247,64 @@ describe('txPool', function () { describe('ready', function () { describe('method addReady/getReady', function () { - var txs = []; + var allTransactions = []; transactions.forEach(function (e) { if (Array.isArray(e)) { - txs = txs.concat(e); + allTransactions = allTransactions.concat(e); } else { - txs.push(e); + allTransactions.push(e); } }); - txs.pop(); + allTransactions.pop(); it('should be ok when add transactions to ready', function (done) { - txPool.addReady(txs, function (err, cbtx) { - expect(cbtx).to.be.undefined; - poolTotals.ready += txs.length -1; + transactionPool.addReady(allTransactions, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; + poolTotals.ready += allTransactions.length -1; done(); }); }); it('should be ok when get transactions from ready', function (done) { - var readyTxs = txPool.getReady(); + var readyTransactions = transactionPool.getReady(); - expect(readyTxs[0].fee).to.be.at.least(readyTxs[1].fee); - expect(readyTxs[1].fee).to.be.at.least(readyTxs[2].fee); - expect(readyTxs[2].fee).to.be.at.least(readyTxs[3].fee); - expect(readyTxs[3].fee).to.be.at.least(readyTxs[4].fee); - expect(readyTxs[4].fee).to.be.at.least(readyTxs[5].fee); + expect(readyTransactions[0].fee).to.be.at.least(readyTransactions[1].fee); + expect(readyTransactions[1].fee).to.be.at.least(readyTransactions[2].fee); + expect(readyTransactions[2].fee).to.be.at.least(readyTransactions[3].fee); + expect(readyTransactions[3].fee).to.be.at.least(readyTransactions[4].fee); + expect(readyTransactions[4].fee).to.be.at.least(readyTransactions[5].fee); done(); }); it('should be ok when add type 2 transaction again to ready', function (done) { - txPool.addReady(transactions[2], function (err, cbtx) { - expect(cbtx).to.be.undefined; + transactionPool.addReady(transactions[2], function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when get transactions from ready', function (done) { - var readyTxs = txPool.getReady(); + var readyTransactions = transactionPool.getReady(); - expect(readyTxs[0].receivedAt).to.not.equal(readyTxs[1].receivedAt); - expect(readyTxs[1].receivedAt).to.equal(readyTxs[2].receivedAt); - expect(readyTxs[2].receivedAt).to.equal(readyTxs[3].receivedAt); - expect(readyTxs[3].receivedAt).to.equal(readyTxs[4].receivedAt); + expect(readyTransactions[0].receivedAt).to.not.equal(readyTransactions[1].receivedAt); + expect(readyTransactions[1].receivedAt).to.equal(readyTransactions[2].receivedAt); + expect(readyTransactions[2].receivedAt).to.equal(readyTransactions[3].receivedAt); + expect(readyTransactions[3].receivedAt).to.equal(readyTransactions[4].receivedAt); done(); }); it('should be ok when delete transaction from ready', function (done) { - var deleteTx = txPool.delete(transactions[0]); + var deleteTransaction = transactionPool.delete(transactions[0]); - expect(deleteTx).to.be.an('array').that.is.not.empty; - expect(deleteTx.length).to.equal(1); - expect(deleteTx[0]).to.equal('ready'); + expect(deleteTransaction).to.be.an('array').that.is.not.empty; + expect(deleteTransaction.length).to.equal(1); + expect(deleteTransaction[0]).to.equal('ready'); poolTotals.ready -= 1; done(); }); it('should be ok when check ready value decreased in 1', function (done) { - var totals = txPool.getUsage(); + var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); expect(totals.ready).to.equal(poolTotals.ready); @@ -1314,17 +1314,17 @@ describe('txPool', function () { }); describe('broadcast transactions', function () { - var broadcastTx; + var broadcastTransaction; it('should be ok when serialize transaction', function (done) { - broadcastTx = bson.serialize(transactions[0]); + broadcastTransaction = bson.serialize(transactions[0]); - expect(broadcastTx).that.is.an('Uint8Array'); + expect(broadcastTransaction).that.is.an('Uint8Array'); done(); }); it('should be ok when deserialized size is greater than serialized size', function (done) { - var serializedLenght = Buffer.from(broadcastTx).length; + var serializedLenght = Buffer.from(broadcastTransaction).length; var deserializedLenght = Buffer.from(JSON.stringify(transactions[0])).length; expect(deserializedLenght).to.be.at.least(serializedLenght); @@ -1332,9 +1332,9 @@ describe('txPool', function () { }); it('should be ok when deserialize transaction', function (done) { - broadcastTx = bson.deserialize(broadcastTx); + broadcastTransaction = bson.deserialize(broadcastTransaction); - expect(broadcastTx).to.deep.equal(transactions[0]); + expect(broadcastTransaction).to.deep.equal(transactions[0]); done(); }); }); @@ -1342,17 +1342,17 @@ describe('txPool', function () { describe('checkBalance', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { - txPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { + transactionPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { expect(cbBalance).to.equal('balance: 52999994'); done(); }); }); it('should fail when checked account balance with not enough LSK for transaction', function (done) { - txPool.checkBalance(invalidsTxs[0], { address: invalidsTxs[0].senderId }, function (err, cbBalance) { + transactionPool.checkBalance(invalidsTransactions[0], { address: invalidsTransactions[0].senderId }, function (err, cbBalance) { expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); done(); }); }); }); -}); \ No newline at end of file +}); From 8accfe1a71346f94d8022b43ec5c60bcbfe4f379 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 24 Oct 2017 18:02:11 +0200 Subject: [PATCH 38/86] New config variables for pool --- config.json | 7 ++++++- test/config.json | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 8b45d04ffa4..e90820ee3ba 100644 --- a/config.json +++ b/config.json @@ -110,7 +110,12 @@ "relayLimit": 2 }, "transactions": { - "maxTxsPerQueue": 1000 + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInteval": 25000 + } }, "forging": { "force": false, diff --git a/test/config.json b/test/config.json index 09e60156d90..7534fa73448 100644 --- a/test/config.json +++ b/test/config.json @@ -72,7 +72,12 @@ "relayLimit": 2 }, "transactions": { - "maxTxsPerQueue": 1000 + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInteval": 25000 + } }, "forging": { "force": true, From b9ee31c31039e58f63e6b7c3b4cd2b7c46bcbeae Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 25 Oct 2017 10:02:11 +0200 Subject: [PATCH 39/86] Adjust function initialization as per config file --- logic/transactions/pool.js | 40 +++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index f43d516667d..5a28159c0fa 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -4,7 +4,6 @@ var async = require('async'); var _ = require('lodash'); var crypto = require('crypto'); -var config = require('../../config.json'); var constants = require('../../helpers/constants.js'); var jobsQueue = require('../../helpers/jobsQueue.js'); var transactionTypes = require('../../helpers/transactionTypes.js'); @@ -12,48 +11,53 @@ var bignum = require('../../helpers/bignum.js'); var slots = require('../../helpers/slots.js'); // Private fields -var modules, library, self, __private = {}, pool = {}; +var modules; +var library; +var self; +var __private = {}; +var pool = {}; /** - * Initializes variables, sets bundled transaction timer and - * transaction expiry timer. + * Initializes variables, sets bundled transaction pool timer and + * transaction pool expiry timer. * @memberof module:transactions * @class * @classdesc Main TransactionPool logic. * @implements {processPool} - * @param {number} broadcastInterval - * @param {number} releaseLimit + * @param {number} storageLimit + * @param {number} processInterval + * @param {number} expiryInterval * @param {Transaction} transaction - Logic instance + * @param {Account} account - Account instance * @param {bus} bus * @param {Object} logger + * @param {Object} ed */ // Constructor -function TransactionPool (broadcastInterval, releaseLimit, poolLimit, poolInterval, poolExpiryInterval, transaction, account, bus, logger, ed) { +function TransactionPool (storageLimit, processInterval, expiryInterval, transaction, account, bus, logger, ed) { library = { logger: logger, bus: bus, ed: ed, logic: { transaction: transaction, - account, account + account: account }, config: { - broadcasts: { - broadcastInterval: broadcastInterval, - releaseLimit: releaseLimit, - }, transactions: { - poolStorageTransactionsLimit: poolLimit, - poolProcessInterval: poolInterval, - poolExpiryInterval: poolExpiryInterval + pool: { + storageLimit: storageLimit, + processInterval: processInterval, + expiryInterval: expiryInterval + } } }, }; self = this; - self.poolStorageTransactionsLimit = library.config.transactions.poolStorageTransactionsLimit; - self.poolProcessInterval = library.config.transactions.poolProcessInterval; - self.poolExpiryInterval = library.config.transactions.poolExpiryInterval; + self.poolStorageTransactionsLimit = library.config.transactions.pool.storageLimit; + self.poolProcessInterval = library.config.transactions.pool.processInterval; + self.poolExpiryInterval = library.config.transactions.pool.expiryInterval; pool = { unverified: { transactions: {}, count: 0 }, verified:{ From 12fff932eaf812590a520fb0d4bf7206e1f82901 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 25 Oct 2017 10:03:51 +0200 Subject: [PATCH 40/86] Implement dbSandbox to init test app --- test/unit/logic/transactions/pool.js | 107 +++++++++------------------ 1 file changed, 36 insertions(+), 71 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index ac95bec4f8b..498d0a5b60b 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -3,21 +3,13 @@ var expect = require('chai').expect; var sinon = require('sinon'); var _ = require('lodash'); -var node = require('../../../node'); -var modulesLoader = require('../../../common/initModule').modulesLoader; -var TransactionPool = require('../../../../logic/transactions/pool.js'); -var Transaction = require('../../../../logic/transaction.js'); -var Account = require('../../../../logic/account.js'); +var node = require('../../../node'); +var DBSandbox = require('../../../common/globalBefore').DBSandbox; +var modulesLoader = require('../../../common/modulesLoader'); var bson = require('../../../../helpers/bson.js'); var constants = require('../../../../helpers/constants.js'); - -var transactionTypes = require('../../../../helpers/transactionTypes'); -var Vote = require('../../../../logic/vote.js'); -var Transfer = require('../../../../logic/transfer.js'); -var Delegate = require('../../../../logic/delegate.js'); -var Signature = require('../../../../logic/signature.js'); -var Multisignature = require('../../../../logic/multisignature.js'); +var TransactionPool = require('../../../../logic/transactions/pool.js'); var testAccounts = [ { @@ -182,76 +174,44 @@ describe('transactionPool', function () { var accounts; var transactionPool; var poolTotals; - var transactionReady; var poolStorageTransactionsLimit; + var dbSandbox; before(function (done) { - constants.unconfirmedTransactionTimeOut = 1; - constants.signatureTransactionTimeOutMultiplier = 1; - constants.secondsPerHour = 1; - modulesLoader.scope.config.transactions.poolStorageTransactionsLimit = 6; - modulesLoader.scope.config.transactions.poolProcessInterval = 60000000; - modulesLoader.scope.config.transactions.poolExpiryInterval = 300000000; - - modulesLoader.initLogicWithDb(Account, function (err, __accountLogic) { + dbSandbox = new DBSandbox(node.config.db, 'lisk_test_logic_transactionPool'); + dbSandbox.create(function (err, __db) { if (err) { return done(err); } - modulesLoader.initLogic(Transaction, modulesLoader.scope, function (err, __trsLogic) { - if (err) { - return done(err); - } - poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.poolStorageTransactionsLimit; + // Wait for genesisBlock transaction being applied + node.initApplication(function (err, scope) { + constants.unconfirmedTransactionTimeOut = 1; + constants.signatureTransactionTimeOutMultiplier = 1; + constants.secondsPerHour = 1; + poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; + modulesLoader.scope.config.transactions.pool.processInterval = 60000000; + modulesLoader.scope.config.transactions.pool.expiryInterval = 300000000; + + // Init transaction logic transactionPool = new TransactionPool( - modulesLoader.scope.config.broadcasts.broadcastInterval, - modulesLoader.scope.config.broadcasts.releaseLimit, - modulesLoader.scope.config.transactions.poolStorageTransactionsLimit, - modulesLoader.scope.config.transactions.poolProcessInterval, - modulesLoader.scope.config.transactions.poolExpiryInterval, - __trsLogic, - __accountLogic, + modulesLoader.scope.config.transactions.pool.storageLimit, + modulesLoader.scope.config.transactions.pool.processInterval, + modulesLoader.scope.config.transactions.pool.expiryInterval, + scope.logic.transaction, + scope.logic.account, modulesLoader.scope.bus, modulesLoader.scope.logger, modulesLoader.scope.ed ); - - modulesLoader.initModules([ - {accounts: require('../../../../modules/accounts')}, - {delegates: require('../../../../modules/delegates')}, - {multisignatures: require('../../../../modules/multisignatures')}, - ], [ - {'transaction': require('../../../../logic/transaction')}, - {'account': require('../../../../logic/account')} - ], {}, function (err, __modules) { - if (err) { - return done(err); - } - var logicDelegates = new Delegate(modulesLoader.scope.schema); - logicDelegates.bind(__modules.accounts); - - var logicVote = new Vote(modulesLoader.scope.logger, modulesLoader.scope.schema); - logicVote.bind(__modules.delegates); - - var logicMultisignature = new Multisignature(modulesLoader.scope.schema, modulesLoader.scope.network, __trsLogic, modulesLoader.scope.logger); - - __modules.accounts.onBind(__modules); - accounts = __modules.accounts; - - __modules.delegates.onBind(__modules); - __modules.multisignatures.onBind(__modules); - - transactionPool.bind(__modules.accounts); - - __trsLogic.attachAssetType(transactionTypes.VOTE, logicVote); - __trsLogic.attachAssetType(transactionTypes.SEND, new Transfer(modulesLoader.scope.logger, modulesLoader.scope.schema)); - __trsLogic.attachAssetType(transactionTypes.DELEGATE, logicDelegates); - __trsLogic.attachAssetType(transactionTypes.SIGNATURE, new Signature(modulesLoader.scope.schema, modulesLoader.scope.logger)); - __trsLogic.attachAssetType(transactionTypes.MULTI, logicMultisignature); - - done(); - }); - }); - }, modulesLoader.scope); + transactionPool.bind( + scope.modules.accounts, + null, + scope.modules.loader + ); + accounts = scope.modules.accounts; + done(); + }, {db: __db}); + }); }); beforeEach(function () { @@ -262,6 +222,11 @@ describe('transactionPool', function () { restoreSpiesState(); }); + after(function (done) { + dbSandbox.destroy(); + node.appCleanup(done); + }); + describe('setup database', function () { it('should be ok when generate account 1', function (done) { From d95818da158fb96c0e39661becbbcf6aa4df6e3b Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 26 Oct 2017 17:03:23 +0200 Subject: [PATCH 41/86] Fix typo --- config.json | 645 +++++++++++++++++++++++++++++++++++++---------- test/config.json | 2 +- 2 files changed, 507 insertions(+), 140 deletions(-) diff --git a/config.json b/config.json index e90820ee3ba..42c50261b1c 100644 --- a/config.json +++ b/config.json @@ -1,143 +1,510 @@ { - "port": 8001, - "httpPort": 8000, - "address": "0.0.0.0", - "version": "0.9.8", - "minVersion": ">=0.9.5", - "fileLogLevel": "info", - "logFileName": "logs/lisk.log", - "consoleLogLevel": "none", - "trustProxy": false, - "topAccounts": false, - "cacheEnabled": false, - "wsWorkers": 1, - "db": { - "host": "localhost", - "port": 5432, - "database": "lisk_main", - "user": "", - "password": "password", - "poolSize": 95, - "poolIdleTimeout": 30000, - "reapIntervalMillis": 1000, - "logEvents": [ - "error" - ] - }, - "redis": { - "host": "127.0.0.1", - "port": 6380, - "db": 0, - "password": null - }, - "api": { - "enabled": true, - "access": { - "public": false, - "whiteList": ["127.0.0.1"] + "port": 5000, + "httpPort": 4000, + "address": "0.0.0.0", + "version": "0.0.0a", + "minVersion": "0.0.0a", + "fileLogLevel": "info", + "logFileName": "logs/lisk.log", + "consoleLogLevel": "debug", + "trustProxy": false, + "topAccounts": false, + "cacheEnabled": true, + "wsWorkers": 1, + "db": { + "host": "localhost", + "port": 5432, + "database": "lisk_test", + "user": "", + "password": "password", + "poolSize": 95, + "poolIdleTimeout": 30000, + "reapIntervalMillis": 1000, + "logEvents": [ + "error" + ] }, - "options": { - "limits": { - "max": 0, - "delayMs": 0, - "delayAfter": 0, - "windowMs": 60000 - } - } - }, - "peers": { - "enabled": true, - "list": [ - { - "ip": "83.136.254.92", - "port": 8000 - }, - { - "ip": "83.136.249.76", - "port": 8000 - }, - { - "ip": "94.237.28.66", - "port": 8000 - }, - { - "ip": "94.237.24.199", - "port": 8000 - }, - { - "ip": "209.50.49.23", - "port": 8000 - }, - { - "ip": "209.50.49.40", - "port": 8000 - }, - { - "ip": "94.237.64.70", - "port": 8000 - }, - { - "ip": "94.237.64.73", - "port": 8000 - }, - { - "ip": "94.237.40.140", - "port": 8000 - }, - { - "ip": "94.237.40.141", - "port": 8000 - } - ], - "access": { - "blackList": [] + "redis": { + "host": "127.0.0.1", + "port": 6380, + "db": 0, + "password": null }, - "options": { - "limits": { - "max": 0, - "delayMs": 0, - "delayAfter": 0, - "windowMs": 60000 - }, - "timeout": 5000 - } - }, - "broadcasts": { - "broadcastInterval": 5000, - "broadcastLimit": 20, - "parallelLimit": 20, - "releaseLimit": 25, - "relayLimit": 2 - }, - "transactions": { - "maxTxsPerQueue": 1000, - "pool": { - "storageLimit": 4000, - "processInterval": 5000, - "expiryInteval": 25000 - } - }, - "forging": { - "force": false, - "secret": [], - "access": { - "whiteList": [ - "127.0.0.1" - ] - } - }, - "loading": { - "verifyOnLoading": false, - "loadPerIteration": 5000 - }, - "ssl": { - "enabled": false, - "options": { - "port": 443, - "address": "0.0.0.0", - "key": "./ssl/lisk.key", - "cert": "./ssl/lisk.crt" - } - }, - "nethash": "ed14889723f24ecc54871d058d98ce91ff2f973192075c0155ba2b7b70ad2511" + "api": { + "enabled": true, + "access": { + "public": true, + "whiteList": ["127.0.0.1"] + }, + "options": { + "limits": { + "max": 0, + "delayMs": 0, + "delayAfter": 0, + "windowMs": 60000 + } + } + }, + "peers": { + "enabled": true, + "list": [{ + "ip": "127.0.0.1", + "port": "5000" + }], + "access": { + "blackList": [] + }, + "options": { + "limits": { + "max": 0, + "delayMs": 0, + "delayAfter": 0, + "windowMs": 60000 + }, + "timeout": 5000 + } + }, + "broadcasts": { + "broadcastInterval": 5000, + "broadcastLimit": 20, + "parallelLimit": 20, + "releaseLimit": 25, + "relayLimit": 2 + }, + "transactions": { + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInterval": 25000 + } + }, + "forging": { + "force": true, + "defaultKey": "elephant tree paris dragon chair galaxy", + "secret": [{ + "encryptedSecret": "19e9f8eee5d9516234a10953669518bf23371d34e114713c8043a98378fd866834946380c4cc0e40f23305643206c1c5be496074f350d09d87735c42eae30c604cabea9862f4fe8f906313c67a7146d54fa844171e6cf925b7c953987082cdd6", + "publicKey": "9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f" + }, + { + "encryptedSecret": "14ac6a589c2d3690dd1638eeccfa5ea6f88bfcf01bdcd65665ede305260f63f3d4ee87cb35ade7c237255a898f080fb160110ab2900108bb99cb9215771b1aaa6892ae48789f6a985b3cedf7ad42e94c", + "publicKey": "141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a" + }, + { + "encryptedSecret": "2df503fb168552063136a479fe5598a28e90261b8ba6c16a8a27ff3ac9b3398aeebe6cf7afe6e84279f204bfcd2a62a18d71e08b14792a456bd3b78e60e215263a3aa2ed401346016e72c2a841e0d236", + "publicKey": "3ff32442bb6da7d60c1b7752b24e6467813c9b698e0f278d48c43580da972135" + }, + { + "encryptedSecret": "4bc610ed8266b31314476d1c3f75ed3d990c6aaa8161697c7b77b703f6114594f2349e1c3ff405c19bde472ec357f2ceb2136507f0cfef9fe40cb220badd62129461b6440b045aff44006adfed9e0a9d", + "publicKey": "5d28e992b80172f38d3a2f9592cad740fd18d3c2e187745cd5f7badf285ed819" + }, + { + "encryptedSecret": "01544bad20422de4502c1d912517afc7cd140a65a852d43425e6f653b9936efc7e34006070c3bf7db0d386a442fde2a25c578cb7293e7236a6b7da79189e92f80ceba3fa1b1e4c73187b88dc7a5f93a5", + "publicKey": "4fe5cd087a319956ddc05725651e56486961b7d5733ecd23e26e463bf9253bb5" + }, + { + "encryptedSecret": "839dfffc57a3106ff441a99668351c6a1ef4fa900673be8ec10293d463c35822a3187437b0f75f36fce7c6b25ef0b5fc302f71cb6f16221f32f5f2a93cff39cc8345d166e9b641b04780f449a9d9024c", + "publicKey": "a796e9c0516a40ccd0eee7a32fdc2dc297fee40a9c76fef9c1bb0cf41ae69750" + }, + { + "encryptedSecret": "2724220f6361569d681d824c6533a169da9958e34538a3a8cac4eb79142cb6be68afdfd7203b44e14bd2a5b7f8bb03f7e01360d5d615c12a918feec4242d4d40db5c83e6fb58dd56ec0c01c74e11a202", + "publicKey": "67651d29dc8d94bcb1174d5bd602762850a89850503b01a5ffde3b726b43d3d2" + }, + { + "encryptedSecret": "dfb05d4adf4fab1d909d7baa4d7d1e97aa98db489ecd547c42d522468c6ff48c71e60423b25bde67e711ecbdc6822c275624f172adda2fcb77e6fdf0ea67cfff36ca9dd61e6b54e0c366037bb629e543", + "publicKey": "c3d1bc76dea367512df3832c437c7b2c95508e140f655425a733090da86fb82d" + }, + { + "encryptedSecret": "9d1e577be94c1970dd7c2926c6060b91c5556dfc9787392db03580e3488af093a88d757689297847e6c3a6a21869a5e2e2d043ea0ee61b4b6ec6d790c5e99aeb9d4db8ab4a97ecb977a7f13c512302d9", + "publicKey": "640dfec4541daed209a455577d7ba519ad92b18692edd9ae71d1a02958f47b1b" + }, + { + "encryptedSecret": "7bd166d384bdccb059dc7935d81b4b96b4542effa747609652284c220cac6e9ceb853c0388cd32fcb526e34da190a0ad19f0f4c94a54cf95f19809bc43fc87e7160e68d924b0a7127e4a3a8dcbc94aae", + "publicKey": "3ea481498521e9fb1201b2295d0e9afa826ac6a3ef51de2f00365f915ac7ac06" + }, + { + "encryptedSecret": "e8e32b31ee24dc0aabaa4c813ef950232966615baa86f97cd49175f035c239863daa4da45bbae75cf507b1642100776b451c303053b3320f4f38d9d56b99859cbb24feb036827fa8d0145fdaa5a1eb9f", + "publicKey": "5c4af5cb0c1c92df2ed4feeb9751e54e951f9d3f77196511f13e636cf6064e74" + }, + { + "encryptedSecret": "aae4115a38be62ec6c1780e1e067da6379e50be5bb173ddd31030d7a71c56ce1070bad4b1dcefd9aade2bef6bb62d2c7560ce6531b208f2fda1e94b013e1e933518b7e65730ad1752ca331cd1e104777", + "publicKey": "399a7d14610c4da8800ed929fc6a05133deb8fbac8403dec93226e96fa7590ee" + }, + { + "encryptedSecret": "a69cf60169a223dd8e78220f01e6b29ebf59fd7b02c44b875fb566452f66abf10f8d255fde4e62319fd02d6928900e7a79782ffe7f75ab6b74fd5bfbe74c555ce604e257719b3829153acbbb5cd81507", + "publicKey": "6e904b2f678eb3b6c3042acb188a607d903d441d61508d047fe36b3c982995c8" + }, + { + "encryptedSecret": "660ad3241aed871fc594e671d6fa6283140329e0a44f8b558f784c5a11dcaa4dffaf2b5cf6ef96463c530f411abcf05eff9693e0c3a1d3982a43e38fc48cffe146ec73d829f35545c87da298ec984eb3cc6ee495d84c62e05f61e14bc16dccb1", + "publicKey": "1af35b29ca515ff5b805a5e3a0ab8c518915b780d5988e76b0672a71b5a3be02" + }, + { + "encryptedSecret": "b9afdf47aa62113cc087a8478161bfd3700c08f81403d40cf8effff3b126c89e69e6b55adda8a0b939a167b530b899501807feb61c4cd6ed8140a98cd535890ca6710d7119e7505cc65f0e7885602662", + "publicKey": "d8daea40fd098d4d546aa76b8e006ce4368c052ffe2c26b6eb843e925d54a408" + }, + { + "encryptedSecret": "762ef1b5972fcea6f705f1d6c7cce5812bcfe457df43b62d3c74c3963569dbecf22268d6c70fc1c36209c8ee91fa31c528b1964a00a19573e5051be50c298940a0aac958097c2c004a400e67bd5dfdf3", + "publicKey": "386217d98eee87268a54d2d76ce9e801ac86271284d793154989e37cb31bcd0e" + }, + { + "encryptedSecret": "d02ea2855af729fe300b3e3a4c1dc569d7fb243b2d18abf489299d6cfd70510c69e37e12096290d1ee414b48c010ee59d1dc822ec23eae3e36be3564fe711a87d0238e2be46d442f6c3d4337d8ad4cdc", + "publicKey": "86499879448d1b0215d59cbf078836e3d7d9d2782d56a2274a568761bff36f19" + }, + { + "encryptedSecret": "9ead8e14a423dcdf6cd9ecdeed9a06e62ceefe74d9511680895e0580d03e31fd61183f2f7c8a84f499bf03931563b8369eb9e8359d248de42f6effa21394a9517465052a74967af42e060e38d2ec0dca70b68b1e8d2959f323c2e3d0cc1e485f", + "publicKey": "948b8b509579306694c00833ec1c0f81e964487db2206ddb1517bfeca2b0dc1b" + }, + { + "encryptedSecret": "8b89056a397700805603aaf120a2a58d86a29964d175c507b2a9d1aed49d9228c0c7add00a52f34b6d5508f0156e1c8711bda256a70bd49e7bed5e830a1798814ca68fd4d2e2f20732fb73adbd0f5aa7", + "publicKey": "b00269bd169f0f89bd2f278788616521dd1539868ced5a63b652208a04ee1556" + }, + { + "encryptedSecret": "ce97114aafa396f49411c2e44f71adc6bb27a64f09b8480269b12de54472e0c139d27ccc8393e94dbf98db246355785be55302d6223ad49516417dd7e872ac87cab07b62f6d65b30084c2d8788029133", + "publicKey": "e13a0267444e026fe755ec128858bf3c519864631e0e4c474ba33f2470a18b83" + }, + { + "encryptedSecret": "2c0ad57580f2c56ecc8e3750dd30c18e0c63272730d3a4d605de572c56e3ee4e34292233e66c69fe3bfa3ad05f7fe8b7778220f1220cdbd0ed3e6b41e43183592229417a808eb747828f62c64a6ef8c37909b21ac324b6d49776e2bdeea8487c", + "publicKey": "1cc68fa0b12521158e09779fd5978ccc0ac26bf99320e00a9549b542dd9ada16" + }, + { + "encryptedSecret": "78ab938c004c6e24ad66ba651c79e67cb4bfd9d1d2c777cdff07393aa736245035c693c2e2255484b70cc855d6f2ac64fe6608e2af8c77a374052c271e44a1e6e4819f3dfe8ef0c6dbf2fd6fefdf0ec1", + "publicKey": "a10f963752b3a44702dfa48b429ac742bea94d97849b1180a36750df3a783621" + }, + { + "encryptedSecret": "da28ab9d4089ded092951ebc3b5ae621a6ceb03e5347d5e3511d5f606d3a430c09593bda2ab6dfe1682ec8dc60385e848818c691ddb2003cae5191712bdc0932477bad199353033189dfcde1fde415ab", + "publicKey": "f33f93aa1f3ddcfd4e42d3206ddaab966f7f1b6672e5096d6da6adefd38edc67" + }, + { + "encryptedSecret": "29ec758f368d3d27c91fcd6d0ae39abceed36350a0d0d055e445d7a4ee197fd3fc86c93516b1f2fd52c893d04cc355e16f7d7c8f80910e75f3720752925f410fb85b6ae68e84486fb328ad2b5932ddce", + "publicKey": "b5341e839b25c4cc2aaf421704c0fb6ba987d537678e23e45d3ca32454a2908c" + }, + { + "encryptedSecret": "f3babd788d4ce719d47ea1e2ee332de7e231d463be019335db89fbbabe34dca066a75cef017d1fed8eb868b32772e0856b2353b3396b7ceb866ad4e6ef791855785ef0a67ce73daceb5e3ec301d777ca", + "publicKey": "da673805f349faf9ca1db167cb941b27f4517a36d23b3c21da4159cff0045fbe" + }, + { + "encryptedSecret": "25ff7ce474bcb643c595769b92ffa306dabe2bbe1249348e7f52ade5baf1784b6d944de1e5e443a4f4b423515d4479893fa61945602388e9f8d20037afe8dc8a152e8297823570a832ba8516e9d0c7fa", + "publicKey": "55405aed8c3a1eabe678be3ad4d36043d6ef8e637d213b84ee703d87f6b250ed" + }, + { + "encryptedSecret": "e93cabe74bf1d1d8c16fcfb5dde983ca85230428d8dc0e33558573e12bcc7e6fcc573b5ae4f2a5b2acdb470699044f9fdf78a90c443e84e82b1a8c636372b8a49261155e29e78662a58d5dece044d12e", + "publicKey": "19ffdf99dee16e4be2db4b0e000b56ab3a4e10bee9f457d8988f75ff7a79fc00" + }, + { + "encryptedSecret": "d592476f0490a1772fe439494e60f8353f75a760696d4a745dc8bccac00624eb4115bdccd759e7b5e0779e67fd7c9c6683f1dada0c950eb879e09f377d04206059a309ef4203b4d361543876d6026d53807b5387db1ddf27ad097fc496a1c318", + "publicKey": "85b07e51ffe528f272b7eb734d0496158f2b0f890155ebe59ba2989a8ccc9a49" + }, + { + "encryptedSecret": "c249b7b202fc6069b56e2cbd452b702b06972591fe49690669a2038b6a2ae362b02d93e0f890b969656e823b282f6bd9cf7f59764dadc04ed109470a063c137ecbd9d3e55d468cedeea614a2b8eb7604", + "publicKey": "8a0bcba8e909036b7a0fdb244f049d847b117d871d203ef7cc4c3917c94fd5fd" + }, + { + "encryptedSecret": "9be521fe8545447b449a8261618939492e008fdd96bc526b43c5359207bc0e9fa48b2b2ebaed60409ec2698c8f0a55bd44aac4437f602e4fd5b58e8567d15f9a0899b4719442cfad28a04a6e4897ab202f595247e5805e66a7ece6a1ec1bf5eb", + "publicKey": "95ea7eb026e250741be85e3593166ef0c4cb3a6eb9114dba8f0974987f10403f" + }, + { + "encryptedSecret": "bb860218efea419b2b790086172c7738e0da1292a60634a61dbf6faf965ce9ca31b3af065466bbbf53054e6b5f91cf0324e95202cda6652fa1be47512cbda11b8df8d90cb21f592bc064d8d2cf48512d", + "publicKey": "cf8a3bf23d1936a34facc4ff63d86d21cc2e1ac17e0010035dc3ef7ae85010dc" + }, + { + "encryptedSecret": "336d7976380ba839c03024a4a721fcf6a382dd6de452408c4c673e12a58ea89e47acf1eb7061c8079948eacb4ecceb2488ddd64f32b7b8bb5ef16200d139151c1ba42514b06c70c939dd79e2e435f191", + "publicKey": "82174ee408161186e650427032f4cfb2496f429b4157da78888cbcea39c387fc" + }, + { + "encryptedSecret": "cd8acda1a7d3ab01588d81d57829c72c9ace85725773f97d82952a487dc07e881fb4671f7db5e39a0bdf015b640069f3e529b13e2c08b7f8dd17329183d9c1af83f8adfe677a1fa1532a563e5d369d9c", + "publicKey": "4bde949c19a0803631768148019473929b5f8661e9e48efb8d895efa9dd24aef" + }, + { + "encryptedSecret": "fa3f176e682eef4f320a679e78d363a30d36cb2d4d2ccd40375e4ca183109737079a2c2f19faf7f171ca0675c4333c77c79f648e508126ce5a6ca6407088de1ae852c3c2877543bb9915e31503401c01", + "publicKey": "2f9b9a43b915bb8dcea45ea3b8552ebec202eb196a7889c2495d948e15f4a724" + }, + { + "encryptedSecret": "14be6dfb3ccdc524e806d133f247f6b7c15de4d644d94aebd1590d30c7fead7eb39563a05ada7100d52d8a2531a06fe50179579c185ffb778655319760cc8680b4574d3d9e136c4d0c3ed5ed9445c032addbd0d00e06f561699930c94db10ad5", + "publicKey": "9503d36c0810f9ac1a9d7d45bf778387a2baab151a45d77ac1289fbe29abb18f" + }, + { + "encryptedSecret": "30792dd8681866dc24f7431b3eac010e8b8ea7eb69e284f5d18e0c0e880390605e39b802b3e4429fc5ff76c95481364500799e8a93cf6024cb53feede99d4aa0a3fbc039a5b68968e8eb7ed2d4813a10", + "publicKey": "a50a55d4476bb118ba5121a07b51c185a8fe0a92b65840143b006b9820124df4" + }, + { + "encryptedSecret": "e14da89a592d427fee29dc2cb12391aa7433830cbb022314927d8176b986323bccab7b41c44565a4185a253583b8b7f4366c0f5dc51f468f6d3dbf0ca979278f791ac3d513d4ae674130e45aa0cc60d3", + "publicKey": "fc8672466cc16688b5e239a784cd0e4c0acf214af039d9b2bf7a006da4043883" + }, + { + "encryptedSecret": "08cd2c19af38a002d7cc2e0eac276b50b44b29733b403276214ed0100ed0be3c0e97a077f90cdb0fe6af2f1fc32ffc1909de88ff78415692566c9e89ae870b7f791b304a2561e3816de1775cffb87a7f", + "publicKey": "db821a4f828db977c6a8d186cc4a44280a6ef6f54ac18ec9eb32f78735f38683" + }, + { + "encryptedSecret": "bec6fc3f16029aa51909786063b5b8c12f3ca664f266474c427973b5c41f286fe44faec5a4f905f908607d5ad3d23cabafb579c2f543cef7f91064984bb8bc21b750422261322507be62556e8f5f6241", + "publicKey": "ba7acc3bcbd47dbf13d744e57f696341c260ce2ea8f332919f18cb543b1f3fc7" + }, + { + "encryptedSecret": "3c28141f74443409e36fae12081aa7886d3d0dd3136aecd4e56fa5725d56d49b04407bef4e688578ad8a21ff00ab929f4c0193e6d2332e980b35b8fbf5ca42593a25c34f94024a53f3cc0a2f13453fe0", + "publicKey": "47c8b3d6a9e418f0920ef58383260bcd04799db150612d4ff6eb399bcd07f216" + }, + { + "encryptedSecret": "eda876a3f91e9fca424dbf0264855187c53cceccbf42dbd0c7f146ee0dab772e3404d51187d370f4006fc475cc97aa4407b4510e54c52a7fe13c9e6fd4bafb07f6c8af90bb381e6e1326b12bea03c2f9e3c41f5e3cc56b356f2c30bbc9fd9ab5", + "publicKey": "d1c3a2cb254554971db289b917a665b5c547617d6fd20c2d6051bc5dfc805b34" + }, + { + "encryptedSecret": "8e63726c9d6ba1e640a3ebe20c4b6e93ebf811f99117aa104b82549e27672deff1b85a185cf75f6a3eb81b604fc866481f2c3fb74df9ed745eae239f78350c4652faba9de02a73facbc8581cf8a1f0b2", + "publicKey": "47b9b07df72d38c19867c6a8c12429e6b8e4d2be48b27cd407da590c7a2af0dc" + }, + { + "encryptedSecret": "12770c8e2459638a645e1a98a724a2b527195e89a54ae1322bed24981b3cd98f7603b91762a699818a15ffc613be34996d3f93cfd7f670ca2a69c8e04e5aa72f369f3a34d5b5a808a02c2c7b25ef6c01", + "publicKey": "9a7452495138cf7cf5a1564c3ef16b186dd8ab4f96423f160e22a3aec6eb614f" + }, + { + "encryptedSecret": "ed60de736337910209b2fa2646bb7bc46184744883b7fd88e92d07626b131fd9be74baa5994121ae87ea861b170a340db045495a70e24291f2999ded8c3c393b6ef31cbc31902316852eb0b02395d926", + "publicKey": "c4dfedeb4f639f749e498a2307f1545ddd6bda62e5503ac1832b122c4a5aedf9" + }, + { + "encryptedSecret": "0bd60abe780d8f44f15b9c642adcaac62a4c99e8c251721ed52c76ebfb56c4b32274f6724d2337ad2001ed96385490625569d85b289c863430d45979e2001f0b017429e097a4145d19e7448e39bd8692", + "publicKey": "96c16a6251e1b9a8c918d5821a5aa8dfb9385607258338297221c5a226eca5c6" + }, + { + "encryptedSecret": "46157fa29405eed271ac6e99efc591d9f96ce687bfb34f4f83afc97667f9e316525a937989849244dbae70248cfff8306b46c8f2debdadf1cbe2ffefedf3a350dc75c505766591dcdc903467af84d61389c2b6e7f8fb28742101b15c4e733559", + "publicKey": "910da2a8e20f25ccbcb029fdcafd369b43d75e5bc4dc6d92352c29404acc350f" + }, + { + "encryptedSecret": "34d50948a4a878e48048dc458511526a02a6c013bde2f20963119820c84a1c3cb1b546487d2568c1a278838c4dfac1e89f9fc4615e3b878ca7b8cb2e8bc3d202c9ea94f29125b78df4e7b176e4666c264fec9832b8807173f510363a416c5dda", + "publicKey": "eabfe7093ef2394deb1b84287f2ceb1b55fe638edc3358a28fc74f64b3498094" + }, + { + "encryptedSecret": "59b09b38a8099d51c5538d8c2adf477af746c8c2e29e3501f85af2b2ac60b256d09fa6ed43526f2daef1b30319ea69cd846865782b9ef8955fef797cf7a38a4bf9e4db3e5e12b18fdc3301657318d0a439f8da3456214bd62091b2d7ef3a0636", + "publicKey": "94b163c5a5ad346db1c84edaff51604164476cf78b8834b6b610dd03bd6b65d9" + }, + { + "encryptedSecret": "4005aa5a37da35a2adbf235fc652fe36506ecda3b5475c99cfade6bfebc7996295c942bd6f9383dcb48fd687c84884fc2e4102566b79953db79b2f7c3ff37de5979cded948d79c60755727024cb9b2148997a2442a8eec9a818374c3d74e3605", + "publicKey": "6164b0cc68f8de44cde90c78e838b9ee1d6041fa61cf0cfbd834d76bb369a10e" + }, + { + "encryptedSecret": "57c153f9aa17923463be7650b469b0977d3ef14d51bce54cdd02bc441b374884572b9968f337e9899c97b6d39b9d56b72c40df7911e559d2d8d9e07a22f26e15c530673c4ba1e61e0d0a408e03f37024", + "publicKey": "3476bba16437ee0e04a29daa34d753139fbcfc14152372d7be5b7c75d51bac6c" + }, + { + "encryptedSecret": "9734614fbe10994141f706cf66c7efa80f31b3d79f9506947dc978b5a808698bc366500fe35bcc5b5e2536a02ce5d9c79843b4fc459f9d72e6a1355a4a1df80a79195f424d9ead51ffb95792bfd08afd", + "publicKey": "01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746" + }, + { + "encryptedSecret": "f878b494a0917234af38fe71fbedd2b6e8a3382bd43b090243c3ce5ae9d3423b3f3f22fe54ff9752a921cebb5b2ae5319053a7907252d859c90855dd59419e6bea4eae2254be5e0b63f46bea670def99", + "publicKey": "aa33af13b440746b4f24312cba5fa910eb077ce6b16b84ebb482cb7720b5c686" + }, + { + "encryptedSecret": "f9b2c3470e4d0dfdccc2898f48beafab96678a3dc53c1d8f5ee26e2d21d2820d0d127e84e230280bf7983598a627c5e8c3a36b2de931cbfd5eb98086e25dd0df4b5ea86efbe8c07485c6c37bc2e650fa", + "publicKey": "6f04988de7e63537c8f14e84b0eb51e0ea9c5da8b4b9256243b3e40b1aeccb76" + }, + { + "encryptedSecret": "71fe042bb125a34edd0b2abda091f97e54cd80e17c38d52050334d4d41e59e0d62a294c05b1ea2737f1a65f160e6a10976da3ef8f9600ecfe0437562103566d6998c400aab7dbce69c0ccff39dd1a2e6", + "publicKey": "07935c642c7409c365258c8488760e96a851cee618aec72eeeb135c9c827f0f9" + }, + { + "encryptedSecret": "c857b847713b4fd4b42c0da416b62610cd1cbef635c9ecc2ae5386d691708e085695acad774c5166af2d0ffc821a7b442196b1f5ff6fc1b925169b38c9ca4066bb44cf600b0a3417b8162f238bb2fca8", + "publicKey": "526931663cbee883ff22369172cba091a5dd5fa1200284fa790d7aeca53d37af" + }, + { + "encryptedSecret": "00170536bc8d35142f094661ef2ab8b330bb29774ccc4473f10563e3ec5803a195da029f86ef95760c94ea7af4c9801723a86213f90505b14ac62be2b68297f1f5d222eae763fea7a67d1559f506bf94", + "publicKey": "f7b9751d59dd6be6029aa36a81a3f6436e2970cf4348845ab6254678fb946c18" + }, + { + "encryptedSecret": "eb75d9522694a83ecee93eddf3e935594e15f71fa9555cff68a8ea533fe861deea6d51ab874cfe0e06dd18fe6f26bfa4a1b419b37fd058bb2ef86a021299fc36c6395f8f6edbd2ebce9faf3737ab117d", + "publicKey": "5f6cc5a8aac752d37c676b0d46a798f7625e37dfa1e96091983274e04ab7ffe2" + }, + { + "encryptedSecret": "4b6fbff0e60bb77aa354ea03d79fa65e4639cf4a4a8a77179ca36a3012c963cfc770f36aba0304b87aca6753b2ee84e5cabfc67fc8be44be5f2c4c48bd4330bd2f57b04d2eae104f67e0ca63a365d5e8a33912a9f679b5f61631f60969c33457", + "publicKey": "9c16751dbe57f4dff7b3fb8911a62c0cb2bdee6240e3f3fefe76832788cb14c6" + }, + { + "encryptedSecret": "114932e16d3c19e1cbc7f75db9d854f352f513fb10b673d0cdf60c84d2f3d724acd6e35baaf0d8a84206575564dbbef9d8872ba8cbb3a05bab14d81ec4e5c339950489a01fc1497f2c1bc35ebc5dcd8a", + "publicKey": "ba2ea5e324eeb42fa6f4d1132a1d79911721e8507033bb0abd49715f531877b4" + }, + { + "encryptedSecret": "afee25e10519d0f6e30aa6988c6df49d15893536f48fcf7e4f55ac3b4cafd9d20ea79e55d8b77ec7eeeb6f95168a182c45842aff59064fc2dfe4841458ab84313164f59aff9d5771d07ec7575ad98d2c", + "publicKey": "0186d6cbee0c9b1a9783e7202f57fc234b1d98197ada1cc29cfbdf697a636ef1" + }, + { + "encryptedSecret": "5ffd4ce62804561cce6e29df22b2dd59d6ba165f342ad91d170f5b41f125d079ce691d364a59e2bd5b0e01db3f60f6046947a7ae66a131b9ff751246cbe5cd713370d2a2572edc73c82ffb2b50b3be25", + "publicKey": "edbb9828fbe62da2a59afbc8623e8ebc5ed2f9b7f77a0cd1cdcf55edea30521c" + }, + { + "encryptedSecret": "2fc83a3743527c1c94d167739a3d4e636a38023daec19b5f1f3054bd8a844e90ab437f14d47a1901e47088869365152cad7ae8e1b7a3f49611163e57cbf44d5911ba3767e3ef2d18e5e06bc8bbc8ee4f", + "publicKey": "b6ac700bf890b887e218dbd55b8f6b091dfc5a684d0fd7a6f69db7dc0313b51b" + }, + { + "encryptedSecret": "f620c283fad909e4450d87fdb255e7bb1b41977e3dfd7a8c6233294df032fb92de6e04043374ecf231f43df8277d75081810dbb24be8dd94aff2c0272f73d5065aa8526142db56c775304f121e967eaf", + "publicKey": "62bbb3c41e43df73de2c3f87e6577d095b84cf6deb1b2d6e87612a9156b980f8" + }, + { + "encryptedSecret": "56508d4e78b79390dc14be6631161b9435d3e598f96ced001e3f8cc958f14b96ca9640ea529e021e6cf94d8c97f7e5480d7bbe6e0de7404afe30c5d6c7889853261e7b77e3ad5a20b9e224fa705292dc", + "publicKey": "6fb2e0882cd9d895e1e441b9f9be7f98e877aa0a16ae230ee5caceb7a1b896ae" + }, + { + "encryptedSecret": "02a7c47f23bfb0ff058969a8a8ed8a2fe368b514179d6adf2374a6526d3ec849821b112ce9986c99803156d75775a1a43ae15ab63120c03f04e6360f8c9f0a8a498a148d413373908f015a30b00c9855", + "publicKey": "9a0f19e60581003b70291cf4a874e8217b04871e676b2c53c85a18ab95c2683b" + }, + { + "encryptedSecret": "4243f41e94c7f59c64907d0737dc6a26a1c01f42cbe547b49f61f0fd5694b56e283ae76a53743304e6155cca6af8f7c8a98a9489fc0076081122dbcec2e2d7f66fef6533c4049a5c8859214ca2fdb846", + "publicKey": "1e6ce18addd973ad432f05f16a4c86372eaca054cbdbcaf1169ad6df033f6b85" + }, + { + "encryptedSecret": "b181d7461e15d3e04e99d5c6ae6b3ac1894a4ff334febcf60453e3c08128fa515f87780cfcc7de9f154bc2639efea979d0bcaa9451d15a1fb1a3c573a3b9adeee6a417a14d4de1dcea8b93f09fff097a", + "publicKey": "27f43391cca75cbc82d1750307649508d1d318cd015f1f172b97318f17ab954e" + }, + { + "encryptedSecret": "ae0e1b12d9b2fe16f164f5a694707645117d4638ae9056117fc20f26fe377d1184bf4183c88c7d5a980dd5819cf38cdf675bcf3e4f590d06afdd4d1d040cffa96fb87b202e8cf21c7e5ab8d0540fc5ac", + "publicKey": "644a971f2c0d0d4b657d050fca27e5f9265e3dfa02a71f7fbf834cc2f2a6a4c8" + }, + { + "encryptedSecret": "2fd9d3b86e197fd49482107b643d9adcaf16fb75b32dc3c6795ad069e3406ef9cfc8bae161e9ab91c3bab2793af460f71e0485c951cf856e8797429afc303ecbd6b7bd4f013c81b899c981f742a553a0", + "publicKey": "cdd68a321ea737e82bce23d2208040f79471d36f2e6f84c74ea36ab26245e522" + }, + { + "encryptedSecret": "13f4c8b680c0d43e1ffa53c964325f1edbb40e5061b6a95d84ace18891364c7906d91aa12147fbc2c75d7f1a935337dd4091d29be832389165c0fea5f7ac3d6010ff9b733b03484a530c7c61edde5945", + "publicKey": "f9f6ff873c10c24eba834be28a56415a49c9c67b7c0ee9f106da827847168986" + }, + { + "encryptedSecret": "bd3300de753c603e2807e4691237a16419e7509d21014b508a3a02c635f5f0843f244875605a75c8fbbe00d2f5d8d00c2f58df6d8f1c3a6fb731e11028a020acb49cb1aae991cf5c182d7102bba8ce24", + "publicKey": "fab7b58be4c1e9542c342023b52e9d359ea89a3af34440bdb97318273e8555f0" + }, + { + "encryptedSecret": "a9a98f384a5d79d9032a458fa937777863d358ec99c63c938c47b37eb236bd3fe7982161263e6e277a6bce89bb71f943f7317d639fab1147e86599be451ed46cc025c84cc4cdd0afbb67728c1d6e6a731f4c8824bdfe0c9efac6c2cb82d18ddf", + "publicKey": "1b5a93c7622c666b0228236a70ee1a31407828b71bfb6daaa29a1509e87d4d3c" + }, + { + "encryptedSecret": "b551c1ab0ff78f6418d45fe53473e6f1edac1f9623199b0d7d1d618a798159f45a28f7cab7c9fec0f2288aac38c278845e813c02637a8af240b2dcacb79b71bc87967e8ac5ab9ce5e8d4880fb990c83d3a2117589a8a7c4ff16e850b66a3213b", + "publicKey": "74583aba9c0b92e4f08c8c75e6df341c255ca007971195ff64d6f909dc4b7177" + }, + { + "encryptedSecret": "0b1bb5f43def421b644904099112cf50255c55ce197b8672370b6f236713d2cb3e63f1537883dcc0e1337df5874d448670ea3cedf243379c4161e2223c682f27f7df3569bd82511fd1b5d8d10b96e64987dee45d657c407d798c127c423344b9", + "publicKey": "2b6f49383af36fd9f1a72d5d2708c8c354add89aaea7edc702c420e2d5fdf22e" + }, + { + "encryptedSecret": "898fa0b5b74f82a96c0209544f18f722e69afe986eb1f15b59c5f42ad5d74c89ee7adeb37f07ec08f1b0c08f1381e870e454bb00025a762320f734e70cadcb90af623ee3fb1c68a2c3e19698af609fe6", + "publicKey": "a10ed9c59dac2c4b8264dc34f2d318719fb5f20ecdd8d6be2d7abfe32294f20d" + }, + { + "encryptedSecret": "2b985f0d91b8afc47cbdd97baeb605dde3b43cf03ed508152c287fe81a6bcccf17fec260476bd1b666e34314a7c426c22d0912ec8f9ef51ef24e2fc4cc99b31a14aab7b4b93e7561428cfca7e4293904", + "publicKey": "c61d0822bbdbfe2a0b5503daff0ce8441c623115c94c0cfcf047a51f8b7160d3" + }, + { + "encryptedSecret": "f0a3b90500f90d25accae35247f1a9c31da915039415bd7457ff166d860efc217ac636712f3da910065277eb9594172d11250122be7d806279fddffa38516425dcc1ca0835110a0e8363faedd86ea10b", + "publicKey": "031e27beab583e2c94cb3167d128fc1a356c1ae88adfcfaa2334abffa3ae0b4c" + }, + { + "encryptedSecret": "c3ba451d1782554a7623b5fd05821322175b5dae5d37fabb4ddb1201ce12d6a89827847f6cf484f942cfcec8374471bfbf60015d140ef5bfea443d6d84d89484aff762812991e506101ce076ea6f504c", + "publicKey": "9986cedd4b5a28e4c81d9b4bff0461dddaa25099df00b8632fe99e88df28ce73" + }, + { + "encryptedSecret": "b690512b16387a0e8c676da57e8ec6ae941d6c9bb9bf411a75223eca7b5912f0ce26ecfd9e20bad87f2b2b437ac3a65ed107599e5309d440af190d0cdd964d08f4b8d556a74e7a3d313fa5f3d90d1abb", + "publicKey": "03e811dda4f51323ac712cd12299410830d655ddffb104f2c9974d90bf8c583a" + }, + { + "encryptedSecret": "106ab4fe7329b2b2305bad84cec475533538ad41b9834e4d8d7623a66f6d78dbc5c313e5e4c7023bfb0e62e76df70d74c0cf097de99d23030b9e76add43fe27bda98d5dc6569ef6e4a4d79f720227fcf", + "publicKey": "64db2bce729e302f6021047dfd39b6c53caf83b42da4b5b881cb153a3fb31613" + }, + { + "encryptedSecret": "dbdc922cdd7ebb7f34b1765ed49bfd3ad1602eeac08959fcf56235b9eb87ab156119990e4de1d4ee3817d735f861b5d57a378549fd084826ed6281d46cc27113a0e7f09d6f8e9116ca80f85d1d690444b7c32320f53c645dd93a01b579ebf0ee", + "publicKey": "f827f60366fae9f9ed65384979de780f4a18c6dbfbefb1c7d100957dde51a06d" + }, + { + "encryptedSecret": "8b020a97c8923d6c0f6478d8f4e107dc4144c6e06631c9ec6f400cfe35583af521149f03b3f93f2d3d11972afad0f3c464ee93cf42b4fbc2da618c03df4dd297c0e1e9a4d3e57df83736081f8cde1b4c", + "publicKey": "68680ca0bcd4676489976837edeac305c34f652e970386013ef26e67589a2516" + }, + { + "encryptedSecret": "14858db09f3c91ba1d593eb6629029b681738e2e0f900cfd8a02d4b272f24c932a02c640b04bf1454e9373b0864bc0ebdce685c4e7027ecf918a75ddc013c944144b39d316d33c94b06284ec4c62bcb7", + "publicKey": "f25af3c59ac7f5155c7a9f36762bd941b9dc9c5c051a1bc2d4e34ed773dd04a3" + }, + { + "encryptedSecret": "1e78d9f0c6df02fd0f3d4342fbb9a69b4ccd7ae19b4c34e1efea6ebb33055fb8661b2012b2a51ff37ff792e363375d8bc50d9632ca1456313cedf5632726000d1f6085c6a7b1af7522a8ec77e7e2452d", + "publicKey": "d3e3c8348bca51461eabfc382f8a01e8e284db54104ad37ec0695d48ae5531ac" + }, + { + "encryptedSecret": "8bf566f5535b678a71c3791de7e424385bf49b9b9ab89ca99305004cc17a557db3c9ea9b82b6a8874afd6e99ae642c41f4d2750efcdfbe06885f231c78c6289cf8e57807c0f86fdc683dcca37eca4b39", + "publicKey": "3be2eb47134d5158e5f7d52076b624b76744b3fba8aa50791b46ba21408524c9" + }, + { + "encryptedSecret": "841c73811a19a87413d971f11bed92f912c296a4602d4103aea9a632acdc583f0917a1cbd84bcd4b5b0eb0d216b1c0d7068c637099f1cacb11cd39738fc555e7de53a7aa181a0502c1fce60887abefa4a3ab119927d6e2e6228108c9b9f96d95", + "publicKey": "9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c" + }, + { + "encryptedSecret": "c35c3b607292200a1a0f00b00c5b63bba049c873557189296667db63f212e1964afd2c9643de049f6257207340fb05f4de633929b540456f0f0672205a78ae1fb503760d40139a91cfff1ffa38f76856", + "publicKey": "e818ac2e8e9ffacd2d49f0f2f6739e16711644194d10bb1a8e9e434603125fa1" + }, + { + "encryptedSecret": "d9cf9f01f5d2a9674b679e97af437f4ca994b33eb7eaef246cecc584a3da1bc6b1af954a1a20ee8ae32f1eb0b2caf4f667ce14b418eb22348aa35ded35ae450b01734cf5ee3ac75e3b6bc75559a81148", + "publicKey": "19d55c023d85d6061d1e196fa440a50907878e2d425bcd893366fa04bc23b4de" + }, + { + "encryptedSecret": "9188d16f6ffcb204a2b2222b4d134c40a848a7220341a888f02482f18c2008b824d7e72832fa8ac8a894016c3e5c84236144021cf94b3f56d2f88a8155f6c8653803ee55cf641b3063483e1933f8745c", + "publicKey": "6d462852d410e84ca199a34d7ccad443784471f22cf3de37c531ce3b87ebbc41" + }, + { + "encryptedSecret": "2127f7e5cf7de58d4843d4871caaa200c8a421a629b59957e26c1bd2f49d74b51be231f1287dc06eb10b317a2dffeb62ead694b53d2551114ac795d94ec61c32ef81339edc2d93cf9b2cdbefe9a833b7", + "publicKey": "e6d075e3e396673c853210f74f8fe6db5e814c304bb9cd7f362018881a21f76c" + }, + { + "encryptedSecret": "98b2c027ab39e00c83f1fd097a787f71d39a3726f8afdb465ddc5e02def76058d9af6c455471a0af00b88358d6ca035b6aa354833356190332867aa8c58598be3dbebbcd4a477b3731256e2aa0d15561", + "publicKey": "0779ca873bbda77f2850965c8a3a3d40a6ee4ec56af55f0a3f16c7c34c0f298b" + }, + { + "encryptedSecret": "ef735fee1bf053c49d13c339163d66484700a784b4ce211624160c25b3876a3e37fb4ca4a931dcba359f423338574e43a62c92d812d078c3f07408c809f596654487899710f57ae8e7012eabb9f52a0b", + "publicKey": "73fec19d4bfe361c0680a7cfd24b3f744a1c1b29d932c4d89ce6157679f8af7d" + }, + { + "encryptedSecret": "e4f0a5a8580bf536196bb38d443a302374ce63ddc6ffc6487369af057818a781dc78a8ab00bf9c66de9dc241dfa3b5175594ccdf86a901a71969d6d4bf0b2884e0e0a5a63c793ca1f9c7bb87f1b0bd627f9f911d63218887e42414bb2d3ce811", + "publicKey": "1e82c7db09da2010e7f5fef24d83bc46238a20ef7ecdf12d9f32e4318a818777" + }, + { + "encryptedSecret": "b50a2013cb0f27eb6e75180094fff80328d3a28e89f99dae0d7ea84ed99a9d4bec9e7cb04207637af1f89a153408fe8d38e501ee6e0f08702486e5a31a6a251a41588e623df78617eb184022ebd86906", + "publicKey": "e42bfabc4a61f02131760af5f2fa0311007932a819a508da25f2ce6af2468156" + }, + { + "encryptedSecret": "4aef02c3564a17354ed8e292c6ea8b184137a6350f3a697a99bdf09dabe5674bc7939a0d4870545124fd08006a2c8399e8be1efbdb82fc6af0b0cafc0d4ee2e34c360ed1886c5d0970269f6ad3bdd951", + "publicKey": "bf9f5cfc548d29983cc0dfa5c4ec47c66c31df0f87aa669869678996902ab47f" + }, + { + "encryptedSecret": "56c5bf16c34d277cf9e70f5b1017a14bc42488f2ae293ec2fff65379381939606e1c0fe9b7876147c91a98957c6b2c62b5798ef554778b691b71826d81a54a119e2668f811436e3c4bd2f240cef7aa6e", + "publicKey": "b137de324fcc79dd1a21ae39a2ee8eed05e76b86d8e89d378f8bb766afb8719f" + }, + { + "encryptedSecret": "b9e8fe42467bd1a5b2c156f6c6f529e7c47943bcf5c67e8c31b8ff2954377e7035b29972ac4199e7e61ae53a48b1b360ffb0b6e3b13629d306842774253eaf937031f2e05ae538c04026a03574641fba", + "publicKey": "31402977c7eaf9e38d18d0689a45d719d615de941f7e80f6db388453b46f4df5" + }, + { + "encryptedSecret": "8741cb1bbfe2b801f0ef2faf43a1c7ba3899e93f4f64ad66707d9a7df21613b9483d8e915c9b15370ad5f7b073999823b6977ac90c10d47fed3618b9e4563e9ae6ca6278707755183ec62cb91daf0efd", + "publicKey": "f62062b7590d46f382fb8c37a26ab0a1bd512951777aedcaa96822230727d3a1" + }, + { + "encryptedSecret": "6a7c5a4b99eb340bbb554adb7d51ea4cac5e5047f1c7b80084dc5cd600a536b7311fecb41d5296278a85d2742b2a24b9aebb144fb244c3b3bb452180eef604ef3f0bf6b9cadd02539246c880a771f4972f9fdb13b3ca28a8cddbfa5895577e22", + "publicKey": "76c9494237e608d43fd6fb0114106a7517f5503cf79d7482db58a02304339b6c" + }, + { + "encryptedSecret": "8c639a2e1eb86b19644c820584d72ff5c6c896e633342b1ecc4c450f92d4cf7b6b143c6fc8b3be4fb85077028fd75197e17e46fe6f319bcffff7c9c8c2c13e77c24ef529d290f3c7632f0ae66b6111233bfad9fd99adff3f45f2ced65b0e9ef7", + "publicKey": "addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9" + }, + { + "encryptedSecret": "47f7103ecc7c7d1678e311533632fe970b9f85ab32f22ace7be420c46f3a4926f3d29ab6c2e33df3f2160965c4109c72474503f3db45076a03e43c3024c7ad00fc312022b599bac6893f2a6770b80e69", + "publicKey": "904c294899819cce0283d8d351cb10febfa0e9f0acd90a820ec8eb90a7084c37" + } + ], + "access": { + "whiteList": [ + "127.0.0.1" + ] + } + }, + "loading": { + "verifyOnLoading": false, + "loadPerIteration": 5000 + }, + "ssl": { + "enabled": false, + "options": { + "port": 443, + "address": "0.0.0.0", + "key": "./ssl/lisk.key", + "cert": "./ssl/lisk.crt" + } + }, + "nethash": "198f2b61a8eb95fbeed58b8216780b68f697f26b849acf00c8c93bb9b24f783d" } diff --git a/test/config.json b/test/config.json index 7534fa73448..42c50261b1c 100644 --- a/test/config.json +++ b/test/config.json @@ -76,7 +76,7 @@ "pool": { "storageLimit": 4000, "processInterval": 5000, - "expiryInteval": 25000 + "expiryInterval": 25000 } }, "forging": { From f6703f577acb03785a49ffaa5a13982475341144 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 26 Oct 2017 17:04:59 +0200 Subject: [PATCH 42/86] Order list, add reverse option and return array --- logic/transactions/pool.js | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 5a28159c0fa..bbcb5885992 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -67,8 +67,8 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac invalid: { transactions: {}, count: 0 } }; - // Bundled transaction timer - function nextBundle (cb) { + // Pool cycle timer + function nextPoolCycle (cb) { self.processPool(function (err) { if (err) { library.logger.log('processPool transaction timer', err); @@ -77,7 +77,7 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac }); } - jobsQueue.register('transactionPoolNextBundle', nextBundle, self.poolProcessInterval); + jobsQueue.register('transactionPoolNextCycle', nextPoolCycle, self.poolProcessInterval); // Transaction expiry timer function nextExpiry (cb) { @@ -102,23 +102,20 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac // Private /** - * Gets all or limited number of transactions from input array. + * Gets all or limited number of transactions from input object list and returns ordered array. * @private - * @param {transaction[]} transactions + * @param {transaction{}} transactions + * @param {boolean} reverse * @param {number} limit * @return {transaction[]} */ -__private.getTransactionsFromPoolList = function (transactionsInPool, limit) { - var transactions = {}; +__private.getTransactionsFromPoolList = function (transactionsInPool, reverse, limit) { + var transactions = _.orderBy(transactionsInPool, ['receivedAt'],['asc']); + + transactions = reverse ? transactions.reverse() : transactions; if (limit) { - var i = 1; - for (var key in transactionsInPool) { - transactions[key] = transactionsInPool[key]; - if (++i > limit) { break; } - } - } else { - transactions = transactionsInPool; + transactions.splice(limit); } return transactions; @@ -195,7 +192,7 @@ __private.addReady = function (transaction, poolList, cb) { }; /** - * Crates signature based on multisignature transaction and secret. + * Creates signature based on multisignature transaction and secret. * @private * @param {transaction} transaction * @param {String} secret @@ -442,11 +439,11 @@ TransactionPool.prototype.get = function (id) { TransactionPool.prototype.getAll = function (filter, params) { switch (filter) { case 'unverified': - return __private.getTransactionsFromPoolList(pool.unverified.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.unverified.transactions, params.reverse, params.limit); case 'pending': - return __private.getTransactionsFromPoolList(pool.verified.pending.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.verified.pending.transactions, params.reverse, params.limit); case 'ready': - return __private.getTransactionsFromPoolList(pool.verified.ready.transactions, params.limit); + return __private.getTransactionsFromPoolList(pool.verified.ready.transactions, params.reverse, params.limit); case 'sender_id': return __private.getAllPoolTransactionsByFilter({'senderId': params.id}); case 'sender_pk': @@ -463,7 +460,7 @@ TransactionPool.prototype.getAll = function (filter, params) { /** * Gets ready transactions ordered by fee and received time. * @param {number} limit - * @return {[transaction]} + * @return {transaction[]} */ TransactionPool.prototype.getReady = function (limit) { var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'asc']); From 3cf74575444d3673447f5a8876b19c8a1a3b31c7 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 26 Oct 2017 17:14:52 +0200 Subject: [PATCH 43/86] Receive transaction id instead of transaction --- logic/transactions/pool.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index bbcb5885992..e94b5133df9 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -603,21 +603,21 @@ TransactionPool.prototype.addSignature = function (transactionId, secret, cb) { /** * Deletes transaction from pool list. * @implements {__private.delete} - * @param {transaction} transaction + * @param {string} id transaction id * @return {Array} names of cleared lists */ -TransactionPool.prototype.delete = function (transaction) { +TransactionPool.prototype.delete = function (id) { var clearedList = []; var poolList = ['unverified','pending','ready']; [pool.unverified, pool.verified.pending, pool.verified.ready].forEach(function (list, index) { - if (__private.delete(transaction.id, list)) { + if (__private.delete(id, list)) { clearedList.push(poolList[index]); } }); if (clearedList.length > 0) { if (clearedList.length > 1) { - library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transactionid:', transaction.id].join(' ')); + library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transaction id:', id].join(' ')); } } return clearedList; From cbf8078be7154ccd659108b05ad56d613ad60e08 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 27 Oct 2017 11:54:49 +0200 Subject: [PATCH 44/86] Add broadcast field to transaction --- logic/transactions/pool.js | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e94b5133df9..e7fcc65b434 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -24,6 +24,8 @@ var pool = {}; * @class * @classdesc Main TransactionPool logic. * @implements {processPool} + * @implements {expireTransactions} + * @implements {resetInvalidTransactions} * @param {number} storageLimit * @param {number} processInterval * @param {number} expiryInterval @@ -64,7 +66,8 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac pending: { transactions: {}, count: 0 }, ready: { transactions: {}, count: 0 } }, - invalid: { transactions: {}, count: 0 } + invalid: { transactions: {}, count: 0 }, + broadcast: [] }; // Pool cycle timer @@ -96,7 +99,7 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac library.logger.debug(['Cleared invalid transactions:', self.resetInvalidTransactions()].join(' ')); } - jobsQueue.register('transactionPoolNextReset', nextReset, self.poolExpiryInterval * 10); + jobsQueue.register('transactionPoolNextReset', nextReset, self.poolExpiryInterval); } @@ -156,12 +159,13 @@ __private.transactionInPool = function (id) { * Adds transactions to pool list. * Checks if transaction is in pool. Checks pool limit. * @implements {__private.transactionInPool} - * @param {transaction} transaction + * @param {Transaction} transaction + * @param {Object} poolList * @param {Object} poolList * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -__private.add = function (transaction, poolList, cb) { +__private.add = function (transaction, poolList, broadcast, cb) { if (__private.countTransactionsPool() >= self.poolStorageTransactionsLimit) { return setImmediate(cb, 'Transaction pool is full'); } @@ -171,6 +175,7 @@ __private.add = function (transaction, poolList, cb) { if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); } else { + transaction.broadcast = broadcast; poolList.transactions[transaction.id] = transaction; poolList.count++; return setImmediate(cb); @@ -307,6 +312,7 @@ __private.transactionTimeOut = function (transaction) { * @returns {setImmediateCallback} errors | sender */ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { + delete transaction.broadcast; async.waterfall([ function setAccountAndGet (waterCb) { modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); @@ -532,16 +538,17 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { /** * Adds transactions to unverified pool list. * @implements {__private.add} - * @param {transaction} transaction + * @param {transaction} transactions + * @param {boolean} broadcast * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -TransactionPool.prototype.add = function (transactions, cb) { +TransactionPool.prototype.add = function (transactions, broadcast, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } - async.eachSeries(transactions, function (transaction, eachSeriesCb) { - __private.add(transaction, pool.unverified, eachSeriesCb); + async.eachSeries(transactions, function (transaction, broadcast, eachSeriesCb) { + __private.add(transaction, pool.unverified, broadcast, eachSeriesCb); }, function (err) { return setImmediate(cb, err); }); @@ -642,7 +649,7 @@ TransactionPool.prototype.processPool = function (cb) { async.eachSeries(pool.unverified.transactions, function (transaction, eachSeriesCb) { __private.delete(transaction.id, pool.unverified); - __private.processUnverifiedTransaction(transaction, true, function (err, sender) { + __private.processUnverifiedTransaction(transaction, transaction.broadcast, function (err, sender) { if (err) { library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); return setImmediate(eachSeriesCb); From e9967a852da841c85258de8b14403968bcf01849 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 27 Oct 2017 13:57:39 +0200 Subject: [PATCH 45/86] Validate tx when add, adjust methods names --- logic/transactions/pool.js | 156 +++++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e7fcc65b434..d358985210d 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -156,16 +156,16 @@ __private.transactionInPool = function (id) { }; /** - * Adds transactions to pool list. - * Checks if transaction is in pool. Checks pool limit. + * Adds transactions to unverified pool list. + * Checks if transaction is in pool, pool limit and performs basic transaction validations. + * @implements {__private.countTransactionsPool} * @implements {__private.transactionInPool} * @param {Transaction} transaction - * @param {Object} poolList - * @param {Object} poolList + * @param {boolean} broadcast * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -__private.add = function (transaction, poolList, broadcast, cb) { +__private.addToUnverified = function (transaction, broadcast, cb) { if (__private.countTransactionsPool() >= self.poolStorageTransactionsLimit) { return setImmediate(cb, 'Transaction pool is full'); } @@ -175,27 +175,89 @@ __private.add = function (transaction, poolList, broadcast, cb) { if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); } else { - transaction.broadcast = broadcast; - poolList.transactions[transaction.id] = transaction; - poolList.count++; - return setImmediate(cb); + async.waterfall([ + function setAccountAndGet (waterCb) { + modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); + }, + function getRequester (sender, waterCb) { + var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; + + if (multisignatures) { + transaction.signatures = transaction.signatures || []; + } + + if (sender && transaction.requesterPublicKey && multisignatures) { + modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { + if (!requester) { + return setImmediate(waterCb, 'Requester not found'); + } else { + return setImmediate(waterCb, null, sender, requester); + } + }); + } else { + return setImmediate(waterCb, null, sender, null); + } + }, + function processTransaction (sender, requester, waterCb) { + library.logic.transaction.process(transaction, sender, requester, function (err) { + if (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, sender); + } + }); + }, + function normalizeTransaction (sender, waterCb) { + try { + transaction = library.logic.transaction.objectNormalize(transaction); + return setImmediate(waterCb, null, sender); + } catch (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err); + } + } + ], function (err, sender) { + if (!err) { + if (broadcast) { + transaction.broadcast = true; + } + pool.unverified.transactions[transaction.id] = transaction; + pool.unverified.count++; + } + return setImmediate(cb, err, sender); + }); } }; /** - * Adds transactions to pool list. - * Clear transaction if is in pool. + * Adds transactions to pool list without checks. * @param {transaction} transaction * @param {Object} poolList * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -__private.addReady = function (transaction, poolList, cb) { +__private.addToPoolList = function (transaction, poolList, cb) { poolList.transactions[transaction.id] = transaction; poolList.count++; return setImmediate(cb); }; +/** + * Adds transactions to pool list without checks. + * @param {transaction} transaction + * @param {Object} poolList + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.addReadyCeckBroadcast = function (transaction, poolList, cb) { + if (transaction.broadcast) { + delete transaction.broadcast; + pool.broadcast.push(transaction); + } + return __private.addToPoolList(transaction, pool.verified.ready, cb); +}; + /** * Creates signature based on multisignature transaction and secret. * @private @@ -299,62 +361,21 @@ __private.transactionTimeOut = function (transaction) { }; /** - * Gets sender account, verifies multisignatures, gets requester, - * process transaction and verifies. + * Gets sender account, and verifies transaction. * @private * @implements {accounts.setAccountAndGet} * @implements {accounts.getAccount} * @implements {logic.transaction.process} * @implements {logic.transaction.verify} * @param {transaction} transaction - * @param {object} broadcast * @param {function} cb - Callback function * @returns {setImmediateCallback} errors | sender */ -__private.processUnverifiedTransaction = function (transaction, broadcast, cb) { - delete transaction.broadcast; +__private.processUnverifiedTransaction = function (transaction, cb) { async.waterfall([ function setAccountAndGet (waterCb) { modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); }, - function getRequester (sender, waterCb) { - var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; - - if (multisignatures) { - transaction.signatures = transaction.signatures || []; - } - - if (sender && transaction.requesterPublicKey && multisignatures) { - modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { - if (!requester) { - return setImmediate(waterCb, 'Requester not found'); - } else { - return setImmediate(waterCb, null, sender, requester); - } - }); - } else { - return setImmediate(waterCb, null, sender, null); - } - }, - function processTransaction (sender, requester, waterCb) { - library.logic.transaction.process(transaction, sender, requester, function (err) { - if (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, sender); - } - }); - }, - function normalizeTransaction (sender, waterCb) { - try { - transaction = library.logic.transaction.objectNormalize(transaction); - return setImmediate(waterCb, null, sender); - } catch (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } - }, function verifyTransaction (sender, waterCb) { library.logic.transaction.verify(transaction, sender, function (err) { if (err) { @@ -366,10 +387,6 @@ __private.processUnverifiedTransaction = function (transaction, broadcast, cb) { }); } ], function (err, sender) { - if (!err) { - library.bus.message('unverifiedTransaction', transaction, broadcast); - } - return setImmediate(cb, err, sender); }); }; @@ -537,7 +554,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { /** * Adds transactions to unverified pool list. - * @implements {__private.add} + * @implements {__private.addToUnverified} * @param {transaction} transactions * @param {boolean} broadcast * @param {function} cb - Callback function. @@ -548,7 +565,7 @@ TransactionPool.prototype.add = function (transactions, broadcast, cb) { transactions = [transactions]; } async.eachSeries(transactions, function (transaction, broadcast, eachSeriesCb) { - __private.add(transaction, pool.unverified, broadcast, eachSeriesCb); + __private.addToUnverified(transaction, broadcast, eachSeriesCb); }, function (err) { return setImmediate(cb, err); }); @@ -556,9 +573,9 @@ TransactionPool.prototype.add = function (transactions, broadcast, cb) { /** * Adds transactions to verified.ready pool list. - * @implements {__private.addReady} + * @implements {__private.addToPoolList} * @implements {delete} - * @param {transaction} transaction + * @param {transaction} transactions * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -570,7 +587,7 @@ TransactionPool.prototype.addReady = function (transactions, cb) { async.eachSeries(transactions, function (transaction, eachSeriesCb) { self.delete(transaction); transaction.receivedAt = resetReceivedAt; - __private.addReady(transaction, pool.verified.ready, eachSeriesCb); + __private.addToPoolList(transaction, pool.verified.ready, eachSeriesCb); }, function (err) { return setImmediate(cb, err); }); @@ -649,7 +666,7 @@ TransactionPool.prototype.processPool = function (cb) { async.eachSeries(pool.unverified.transactions, function (transaction, eachSeriesCb) { __private.delete(transaction.id, pool.unverified); - __private.processUnverifiedTransaction(transaction, transaction.broadcast, function (err, sender) { + __private.processUnverifiedTransaction(transaction, function (err, sender) { if (err) { library.logger.error('Failed to process unverified transaction: ' + transaction.id, err); return setImmediate(eachSeriesCb); @@ -663,10 +680,9 @@ TransactionPool.prototype.processPool = function (cb) { var receiveAtToTime = transaction.receivedAt.getTime(); var timestampToTime = slots.getRealTime(transaction.timestamp); if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { - __private.add(transaction, pool.verified.pending, eachSeriesCb); + __private.addToPoolList(transaction, pool.verified.pending, eachSeriesCb); } else { - // check transaction and if ok add to verified.ready - __private.add(transaction, pool.verified.ready, eachSeriesCb); + __private.addReadyCheckBroadcast(transaction, eachSeriesCb); } }); }); @@ -688,7 +704,7 @@ TransactionPool.prototype.processPool = function (cb) { transaction.signatures.length >= transaction.asset.multisignature.min ) { __private.delete(transaction.id, pool.verified.pending); - __private.add(transaction, pool.verified.ready, eachSeriesCb); + __private.addReadyCheckBroadcast(transaction, eachSeriesCb); } else { return setImmediate(eachSeriesCb); } @@ -697,6 +713,8 @@ TransactionPool.prototype.processPool = function (cb) { }); } }, function (err) { + library.bus.message('unverifiedTransaction', pool.broadcast); + pool.broadcast = []; return setImmediate(cb, err); }); }; From 9dbae48bc09b256872d30af3c5904861010901e8 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 27 Oct 2017 14:04:58 +0200 Subject: [PATCH 46/86] Restore config.json --- config.json | 645 +++++++++++----------------------------------------- 1 file changed, 139 insertions(+), 506 deletions(-) diff --git a/config.json b/config.json index 42c50261b1c..e7e8265ff12 100644 --- a/config.json +++ b/config.json @@ -1,510 +1,143 @@ { - "port": 5000, - "httpPort": 4000, - "address": "0.0.0.0", - "version": "0.0.0a", - "minVersion": "0.0.0a", - "fileLogLevel": "info", - "logFileName": "logs/lisk.log", - "consoleLogLevel": "debug", - "trustProxy": false, - "topAccounts": false, - "cacheEnabled": true, - "wsWorkers": 1, - "db": { - "host": "localhost", - "port": 5432, - "database": "lisk_test", - "user": "", - "password": "password", - "poolSize": 95, - "poolIdleTimeout": 30000, - "reapIntervalMillis": 1000, - "logEvents": [ - "error" - ] + "port": 8001, + "httpPort": 8000, + "address": "0.0.0.0", + "version": "0.9.8", + "minVersion": ">=0.9.5", + "fileLogLevel": "info", + "logFileName": "logs/lisk.log", + "consoleLogLevel": "none", + "trustProxy": false, + "topAccounts": false, + "cacheEnabled": false, + "wsWorkers": 1, + "db": { + "host": "localhost", + "port": 5432, + "database": "lisk_main", + "user": "", + "password": "password", + "poolSize": 95, + "poolIdleTimeout": 30000, + "reapIntervalMillis": 1000, + "logEvents": [ + "error" + ] + }, + "redis": { + "host": "127.0.0.1", + "port": 6380, + "db": 0, + "password": null + }, + "api": { + "enabled": true, + "access": { + "public": false, + "whiteList": ["127.0.0.1"] }, - "redis": { - "host": "127.0.0.1", - "port": 6380, - "db": 0, - "password": null + "options": { + "limits": { + "max": 0, + "delayMs": 0, + "delayAfter": 0, + "windowMs": 60000 + } + } + }, + "peers": { + "enabled": true, + "list": [ + { + "ip": "83.136.254.92", + "port": 8000 + }, + { + "ip": "83.136.249.76", + "port": 8000 + }, + { + "ip": "94.237.28.66", + "port": 8000 + }, + { + "ip": "94.237.24.199", + "port": 8000 + }, + { + "ip": "209.50.49.23", + "port": 8000 + }, + { + "ip": "209.50.49.40", + "port": 8000 + }, + { + "ip": "94.237.64.70", + "port": 8000 + }, + { + "ip": "94.237.64.73", + "port": 8000 + }, + { + "ip": "94.237.40.140", + "port": 8000 + }, + { + "ip": "94.237.40.141", + "port": 8000 + } + ], + "access": { + "blackList": [] }, - "api": { - "enabled": true, - "access": { - "public": true, - "whiteList": ["127.0.0.1"] - }, - "options": { - "limits": { - "max": 0, - "delayMs": 0, - "delayAfter": 0, - "windowMs": 60000 - } - } - }, - "peers": { - "enabled": true, - "list": [{ - "ip": "127.0.0.1", - "port": "5000" - }], - "access": { - "blackList": [] - }, - "options": { - "limits": { - "max": 0, - "delayMs": 0, - "delayAfter": 0, - "windowMs": 60000 - }, - "timeout": 5000 - } - }, - "broadcasts": { - "broadcastInterval": 5000, - "broadcastLimit": 20, - "parallelLimit": 20, - "releaseLimit": 25, - "relayLimit": 2 - }, - "transactions": { - "maxTxsPerQueue": 1000, - "pool": { - "storageLimit": 4000, - "processInterval": 5000, - "expiryInterval": 25000 - } - }, - "forging": { - "force": true, - "defaultKey": "elephant tree paris dragon chair galaxy", - "secret": [{ - "encryptedSecret": "19e9f8eee5d9516234a10953669518bf23371d34e114713c8043a98378fd866834946380c4cc0e40f23305643206c1c5be496074f350d09d87735c42eae30c604cabea9862f4fe8f906313c67a7146d54fa844171e6cf925b7c953987082cdd6", - "publicKey": "9d3058175acab969f41ad9b86f7a2926c74258670fe56b37c429c01fca9f2f0f" - }, - { - "encryptedSecret": "14ac6a589c2d3690dd1638eeccfa5ea6f88bfcf01bdcd65665ede305260f63f3d4ee87cb35ade7c237255a898f080fb160110ab2900108bb99cb9215771b1aaa6892ae48789f6a985b3cedf7ad42e94c", - "publicKey": "141b16ac8d5bd150f16b1caa08f689057ca4c4434445e56661831f4e671b7c0a" - }, - { - "encryptedSecret": "2df503fb168552063136a479fe5598a28e90261b8ba6c16a8a27ff3ac9b3398aeebe6cf7afe6e84279f204bfcd2a62a18d71e08b14792a456bd3b78e60e215263a3aa2ed401346016e72c2a841e0d236", - "publicKey": "3ff32442bb6da7d60c1b7752b24e6467813c9b698e0f278d48c43580da972135" - }, - { - "encryptedSecret": "4bc610ed8266b31314476d1c3f75ed3d990c6aaa8161697c7b77b703f6114594f2349e1c3ff405c19bde472ec357f2ceb2136507f0cfef9fe40cb220badd62129461b6440b045aff44006adfed9e0a9d", - "publicKey": "5d28e992b80172f38d3a2f9592cad740fd18d3c2e187745cd5f7badf285ed819" - }, - { - "encryptedSecret": "01544bad20422de4502c1d912517afc7cd140a65a852d43425e6f653b9936efc7e34006070c3bf7db0d386a442fde2a25c578cb7293e7236a6b7da79189e92f80ceba3fa1b1e4c73187b88dc7a5f93a5", - "publicKey": "4fe5cd087a319956ddc05725651e56486961b7d5733ecd23e26e463bf9253bb5" - }, - { - "encryptedSecret": "839dfffc57a3106ff441a99668351c6a1ef4fa900673be8ec10293d463c35822a3187437b0f75f36fce7c6b25ef0b5fc302f71cb6f16221f32f5f2a93cff39cc8345d166e9b641b04780f449a9d9024c", - "publicKey": "a796e9c0516a40ccd0eee7a32fdc2dc297fee40a9c76fef9c1bb0cf41ae69750" - }, - { - "encryptedSecret": "2724220f6361569d681d824c6533a169da9958e34538a3a8cac4eb79142cb6be68afdfd7203b44e14bd2a5b7f8bb03f7e01360d5d615c12a918feec4242d4d40db5c83e6fb58dd56ec0c01c74e11a202", - "publicKey": "67651d29dc8d94bcb1174d5bd602762850a89850503b01a5ffde3b726b43d3d2" - }, - { - "encryptedSecret": "dfb05d4adf4fab1d909d7baa4d7d1e97aa98db489ecd547c42d522468c6ff48c71e60423b25bde67e711ecbdc6822c275624f172adda2fcb77e6fdf0ea67cfff36ca9dd61e6b54e0c366037bb629e543", - "publicKey": "c3d1bc76dea367512df3832c437c7b2c95508e140f655425a733090da86fb82d" - }, - { - "encryptedSecret": "9d1e577be94c1970dd7c2926c6060b91c5556dfc9787392db03580e3488af093a88d757689297847e6c3a6a21869a5e2e2d043ea0ee61b4b6ec6d790c5e99aeb9d4db8ab4a97ecb977a7f13c512302d9", - "publicKey": "640dfec4541daed209a455577d7ba519ad92b18692edd9ae71d1a02958f47b1b" - }, - { - "encryptedSecret": "7bd166d384bdccb059dc7935d81b4b96b4542effa747609652284c220cac6e9ceb853c0388cd32fcb526e34da190a0ad19f0f4c94a54cf95f19809bc43fc87e7160e68d924b0a7127e4a3a8dcbc94aae", - "publicKey": "3ea481498521e9fb1201b2295d0e9afa826ac6a3ef51de2f00365f915ac7ac06" - }, - { - "encryptedSecret": "e8e32b31ee24dc0aabaa4c813ef950232966615baa86f97cd49175f035c239863daa4da45bbae75cf507b1642100776b451c303053b3320f4f38d9d56b99859cbb24feb036827fa8d0145fdaa5a1eb9f", - "publicKey": "5c4af5cb0c1c92df2ed4feeb9751e54e951f9d3f77196511f13e636cf6064e74" - }, - { - "encryptedSecret": "aae4115a38be62ec6c1780e1e067da6379e50be5bb173ddd31030d7a71c56ce1070bad4b1dcefd9aade2bef6bb62d2c7560ce6531b208f2fda1e94b013e1e933518b7e65730ad1752ca331cd1e104777", - "publicKey": "399a7d14610c4da8800ed929fc6a05133deb8fbac8403dec93226e96fa7590ee" - }, - { - "encryptedSecret": "a69cf60169a223dd8e78220f01e6b29ebf59fd7b02c44b875fb566452f66abf10f8d255fde4e62319fd02d6928900e7a79782ffe7f75ab6b74fd5bfbe74c555ce604e257719b3829153acbbb5cd81507", - "publicKey": "6e904b2f678eb3b6c3042acb188a607d903d441d61508d047fe36b3c982995c8" - }, - { - "encryptedSecret": "660ad3241aed871fc594e671d6fa6283140329e0a44f8b558f784c5a11dcaa4dffaf2b5cf6ef96463c530f411abcf05eff9693e0c3a1d3982a43e38fc48cffe146ec73d829f35545c87da298ec984eb3cc6ee495d84c62e05f61e14bc16dccb1", - "publicKey": "1af35b29ca515ff5b805a5e3a0ab8c518915b780d5988e76b0672a71b5a3be02" - }, - { - "encryptedSecret": "b9afdf47aa62113cc087a8478161bfd3700c08f81403d40cf8effff3b126c89e69e6b55adda8a0b939a167b530b899501807feb61c4cd6ed8140a98cd535890ca6710d7119e7505cc65f0e7885602662", - "publicKey": "d8daea40fd098d4d546aa76b8e006ce4368c052ffe2c26b6eb843e925d54a408" - }, - { - "encryptedSecret": "762ef1b5972fcea6f705f1d6c7cce5812bcfe457df43b62d3c74c3963569dbecf22268d6c70fc1c36209c8ee91fa31c528b1964a00a19573e5051be50c298940a0aac958097c2c004a400e67bd5dfdf3", - "publicKey": "386217d98eee87268a54d2d76ce9e801ac86271284d793154989e37cb31bcd0e" - }, - { - "encryptedSecret": "d02ea2855af729fe300b3e3a4c1dc569d7fb243b2d18abf489299d6cfd70510c69e37e12096290d1ee414b48c010ee59d1dc822ec23eae3e36be3564fe711a87d0238e2be46d442f6c3d4337d8ad4cdc", - "publicKey": "86499879448d1b0215d59cbf078836e3d7d9d2782d56a2274a568761bff36f19" - }, - { - "encryptedSecret": "9ead8e14a423dcdf6cd9ecdeed9a06e62ceefe74d9511680895e0580d03e31fd61183f2f7c8a84f499bf03931563b8369eb9e8359d248de42f6effa21394a9517465052a74967af42e060e38d2ec0dca70b68b1e8d2959f323c2e3d0cc1e485f", - "publicKey": "948b8b509579306694c00833ec1c0f81e964487db2206ddb1517bfeca2b0dc1b" - }, - { - "encryptedSecret": "8b89056a397700805603aaf120a2a58d86a29964d175c507b2a9d1aed49d9228c0c7add00a52f34b6d5508f0156e1c8711bda256a70bd49e7bed5e830a1798814ca68fd4d2e2f20732fb73adbd0f5aa7", - "publicKey": "b00269bd169f0f89bd2f278788616521dd1539868ced5a63b652208a04ee1556" - }, - { - "encryptedSecret": "ce97114aafa396f49411c2e44f71adc6bb27a64f09b8480269b12de54472e0c139d27ccc8393e94dbf98db246355785be55302d6223ad49516417dd7e872ac87cab07b62f6d65b30084c2d8788029133", - "publicKey": "e13a0267444e026fe755ec128858bf3c519864631e0e4c474ba33f2470a18b83" - }, - { - "encryptedSecret": "2c0ad57580f2c56ecc8e3750dd30c18e0c63272730d3a4d605de572c56e3ee4e34292233e66c69fe3bfa3ad05f7fe8b7778220f1220cdbd0ed3e6b41e43183592229417a808eb747828f62c64a6ef8c37909b21ac324b6d49776e2bdeea8487c", - "publicKey": "1cc68fa0b12521158e09779fd5978ccc0ac26bf99320e00a9549b542dd9ada16" - }, - { - "encryptedSecret": "78ab938c004c6e24ad66ba651c79e67cb4bfd9d1d2c777cdff07393aa736245035c693c2e2255484b70cc855d6f2ac64fe6608e2af8c77a374052c271e44a1e6e4819f3dfe8ef0c6dbf2fd6fefdf0ec1", - "publicKey": "a10f963752b3a44702dfa48b429ac742bea94d97849b1180a36750df3a783621" - }, - { - "encryptedSecret": "da28ab9d4089ded092951ebc3b5ae621a6ceb03e5347d5e3511d5f606d3a430c09593bda2ab6dfe1682ec8dc60385e848818c691ddb2003cae5191712bdc0932477bad199353033189dfcde1fde415ab", - "publicKey": "f33f93aa1f3ddcfd4e42d3206ddaab966f7f1b6672e5096d6da6adefd38edc67" - }, - { - "encryptedSecret": "29ec758f368d3d27c91fcd6d0ae39abceed36350a0d0d055e445d7a4ee197fd3fc86c93516b1f2fd52c893d04cc355e16f7d7c8f80910e75f3720752925f410fb85b6ae68e84486fb328ad2b5932ddce", - "publicKey": "b5341e839b25c4cc2aaf421704c0fb6ba987d537678e23e45d3ca32454a2908c" - }, - { - "encryptedSecret": "f3babd788d4ce719d47ea1e2ee332de7e231d463be019335db89fbbabe34dca066a75cef017d1fed8eb868b32772e0856b2353b3396b7ceb866ad4e6ef791855785ef0a67ce73daceb5e3ec301d777ca", - "publicKey": "da673805f349faf9ca1db167cb941b27f4517a36d23b3c21da4159cff0045fbe" - }, - { - "encryptedSecret": "25ff7ce474bcb643c595769b92ffa306dabe2bbe1249348e7f52ade5baf1784b6d944de1e5e443a4f4b423515d4479893fa61945602388e9f8d20037afe8dc8a152e8297823570a832ba8516e9d0c7fa", - "publicKey": "55405aed8c3a1eabe678be3ad4d36043d6ef8e637d213b84ee703d87f6b250ed" - }, - { - "encryptedSecret": "e93cabe74bf1d1d8c16fcfb5dde983ca85230428d8dc0e33558573e12bcc7e6fcc573b5ae4f2a5b2acdb470699044f9fdf78a90c443e84e82b1a8c636372b8a49261155e29e78662a58d5dece044d12e", - "publicKey": "19ffdf99dee16e4be2db4b0e000b56ab3a4e10bee9f457d8988f75ff7a79fc00" - }, - { - "encryptedSecret": "d592476f0490a1772fe439494e60f8353f75a760696d4a745dc8bccac00624eb4115bdccd759e7b5e0779e67fd7c9c6683f1dada0c950eb879e09f377d04206059a309ef4203b4d361543876d6026d53807b5387db1ddf27ad097fc496a1c318", - "publicKey": "85b07e51ffe528f272b7eb734d0496158f2b0f890155ebe59ba2989a8ccc9a49" - }, - { - "encryptedSecret": "c249b7b202fc6069b56e2cbd452b702b06972591fe49690669a2038b6a2ae362b02d93e0f890b969656e823b282f6bd9cf7f59764dadc04ed109470a063c137ecbd9d3e55d468cedeea614a2b8eb7604", - "publicKey": "8a0bcba8e909036b7a0fdb244f049d847b117d871d203ef7cc4c3917c94fd5fd" - }, - { - "encryptedSecret": "9be521fe8545447b449a8261618939492e008fdd96bc526b43c5359207bc0e9fa48b2b2ebaed60409ec2698c8f0a55bd44aac4437f602e4fd5b58e8567d15f9a0899b4719442cfad28a04a6e4897ab202f595247e5805e66a7ece6a1ec1bf5eb", - "publicKey": "95ea7eb026e250741be85e3593166ef0c4cb3a6eb9114dba8f0974987f10403f" - }, - { - "encryptedSecret": "bb860218efea419b2b790086172c7738e0da1292a60634a61dbf6faf965ce9ca31b3af065466bbbf53054e6b5f91cf0324e95202cda6652fa1be47512cbda11b8df8d90cb21f592bc064d8d2cf48512d", - "publicKey": "cf8a3bf23d1936a34facc4ff63d86d21cc2e1ac17e0010035dc3ef7ae85010dc" - }, - { - "encryptedSecret": "336d7976380ba839c03024a4a721fcf6a382dd6de452408c4c673e12a58ea89e47acf1eb7061c8079948eacb4ecceb2488ddd64f32b7b8bb5ef16200d139151c1ba42514b06c70c939dd79e2e435f191", - "publicKey": "82174ee408161186e650427032f4cfb2496f429b4157da78888cbcea39c387fc" - }, - { - "encryptedSecret": "cd8acda1a7d3ab01588d81d57829c72c9ace85725773f97d82952a487dc07e881fb4671f7db5e39a0bdf015b640069f3e529b13e2c08b7f8dd17329183d9c1af83f8adfe677a1fa1532a563e5d369d9c", - "publicKey": "4bde949c19a0803631768148019473929b5f8661e9e48efb8d895efa9dd24aef" - }, - { - "encryptedSecret": "fa3f176e682eef4f320a679e78d363a30d36cb2d4d2ccd40375e4ca183109737079a2c2f19faf7f171ca0675c4333c77c79f648e508126ce5a6ca6407088de1ae852c3c2877543bb9915e31503401c01", - "publicKey": "2f9b9a43b915bb8dcea45ea3b8552ebec202eb196a7889c2495d948e15f4a724" - }, - { - "encryptedSecret": "14be6dfb3ccdc524e806d133f247f6b7c15de4d644d94aebd1590d30c7fead7eb39563a05ada7100d52d8a2531a06fe50179579c185ffb778655319760cc8680b4574d3d9e136c4d0c3ed5ed9445c032addbd0d00e06f561699930c94db10ad5", - "publicKey": "9503d36c0810f9ac1a9d7d45bf778387a2baab151a45d77ac1289fbe29abb18f" - }, - { - "encryptedSecret": "30792dd8681866dc24f7431b3eac010e8b8ea7eb69e284f5d18e0c0e880390605e39b802b3e4429fc5ff76c95481364500799e8a93cf6024cb53feede99d4aa0a3fbc039a5b68968e8eb7ed2d4813a10", - "publicKey": "a50a55d4476bb118ba5121a07b51c185a8fe0a92b65840143b006b9820124df4" - }, - { - "encryptedSecret": "e14da89a592d427fee29dc2cb12391aa7433830cbb022314927d8176b986323bccab7b41c44565a4185a253583b8b7f4366c0f5dc51f468f6d3dbf0ca979278f791ac3d513d4ae674130e45aa0cc60d3", - "publicKey": "fc8672466cc16688b5e239a784cd0e4c0acf214af039d9b2bf7a006da4043883" - }, - { - "encryptedSecret": "08cd2c19af38a002d7cc2e0eac276b50b44b29733b403276214ed0100ed0be3c0e97a077f90cdb0fe6af2f1fc32ffc1909de88ff78415692566c9e89ae870b7f791b304a2561e3816de1775cffb87a7f", - "publicKey": "db821a4f828db977c6a8d186cc4a44280a6ef6f54ac18ec9eb32f78735f38683" - }, - { - "encryptedSecret": "bec6fc3f16029aa51909786063b5b8c12f3ca664f266474c427973b5c41f286fe44faec5a4f905f908607d5ad3d23cabafb579c2f543cef7f91064984bb8bc21b750422261322507be62556e8f5f6241", - "publicKey": "ba7acc3bcbd47dbf13d744e57f696341c260ce2ea8f332919f18cb543b1f3fc7" - }, - { - "encryptedSecret": "3c28141f74443409e36fae12081aa7886d3d0dd3136aecd4e56fa5725d56d49b04407bef4e688578ad8a21ff00ab929f4c0193e6d2332e980b35b8fbf5ca42593a25c34f94024a53f3cc0a2f13453fe0", - "publicKey": "47c8b3d6a9e418f0920ef58383260bcd04799db150612d4ff6eb399bcd07f216" - }, - { - "encryptedSecret": "eda876a3f91e9fca424dbf0264855187c53cceccbf42dbd0c7f146ee0dab772e3404d51187d370f4006fc475cc97aa4407b4510e54c52a7fe13c9e6fd4bafb07f6c8af90bb381e6e1326b12bea03c2f9e3c41f5e3cc56b356f2c30bbc9fd9ab5", - "publicKey": "d1c3a2cb254554971db289b917a665b5c547617d6fd20c2d6051bc5dfc805b34" - }, - { - "encryptedSecret": "8e63726c9d6ba1e640a3ebe20c4b6e93ebf811f99117aa104b82549e27672deff1b85a185cf75f6a3eb81b604fc866481f2c3fb74df9ed745eae239f78350c4652faba9de02a73facbc8581cf8a1f0b2", - "publicKey": "47b9b07df72d38c19867c6a8c12429e6b8e4d2be48b27cd407da590c7a2af0dc" - }, - { - "encryptedSecret": "12770c8e2459638a645e1a98a724a2b527195e89a54ae1322bed24981b3cd98f7603b91762a699818a15ffc613be34996d3f93cfd7f670ca2a69c8e04e5aa72f369f3a34d5b5a808a02c2c7b25ef6c01", - "publicKey": "9a7452495138cf7cf5a1564c3ef16b186dd8ab4f96423f160e22a3aec6eb614f" - }, - { - "encryptedSecret": "ed60de736337910209b2fa2646bb7bc46184744883b7fd88e92d07626b131fd9be74baa5994121ae87ea861b170a340db045495a70e24291f2999ded8c3c393b6ef31cbc31902316852eb0b02395d926", - "publicKey": "c4dfedeb4f639f749e498a2307f1545ddd6bda62e5503ac1832b122c4a5aedf9" - }, - { - "encryptedSecret": "0bd60abe780d8f44f15b9c642adcaac62a4c99e8c251721ed52c76ebfb56c4b32274f6724d2337ad2001ed96385490625569d85b289c863430d45979e2001f0b017429e097a4145d19e7448e39bd8692", - "publicKey": "96c16a6251e1b9a8c918d5821a5aa8dfb9385607258338297221c5a226eca5c6" - }, - { - "encryptedSecret": "46157fa29405eed271ac6e99efc591d9f96ce687bfb34f4f83afc97667f9e316525a937989849244dbae70248cfff8306b46c8f2debdadf1cbe2ffefedf3a350dc75c505766591dcdc903467af84d61389c2b6e7f8fb28742101b15c4e733559", - "publicKey": "910da2a8e20f25ccbcb029fdcafd369b43d75e5bc4dc6d92352c29404acc350f" - }, - { - "encryptedSecret": "34d50948a4a878e48048dc458511526a02a6c013bde2f20963119820c84a1c3cb1b546487d2568c1a278838c4dfac1e89f9fc4615e3b878ca7b8cb2e8bc3d202c9ea94f29125b78df4e7b176e4666c264fec9832b8807173f510363a416c5dda", - "publicKey": "eabfe7093ef2394deb1b84287f2ceb1b55fe638edc3358a28fc74f64b3498094" - }, - { - "encryptedSecret": "59b09b38a8099d51c5538d8c2adf477af746c8c2e29e3501f85af2b2ac60b256d09fa6ed43526f2daef1b30319ea69cd846865782b9ef8955fef797cf7a38a4bf9e4db3e5e12b18fdc3301657318d0a439f8da3456214bd62091b2d7ef3a0636", - "publicKey": "94b163c5a5ad346db1c84edaff51604164476cf78b8834b6b610dd03bd6b65d9" - }, - { - "encryptedSecret": "4005aa5a37da35a2adbf235fc652fe36506ecda3b5475c99cfade6bfebc7996295c942bd6f9383dcb48fd687c84884fc2e4102566b79953db79b2f7c3ff37de5979cded948d79c60755727024cb9b2148997a2442a8eec9a818374c3d74e3605", - "publicKey": "6164b0cc68f8de44cde90c78e838b9ee1d6041fa61cf0cfbd834d76bb369a10e" - }, - { - "encryptedSecret": "57c153f9aa17923463be7650b469b0977d3ef14d51bce54cdd02bc441b374884572b9968f337e9899c97b6d39b9d56b72c40df7911e559d2d8d9e07a22f26e15c530673c4ba1e61e0d0a408e03f37024", - "publicKey": "3476bba16437ee0e04a29daa34d753139fbcfc14152372d7be5b7c75d51bac6c" - }, - { - "encryptedSecret": "9734614fbe10994141f706cf66c7efa80f31b3d79f9506947dc978b5a808698bc366500fe35bcc5b5e2536a02ce5d9c79843b4fc459f9d72e6a1355a4a1df80a79195f424d9ead51ffb95792bfd08afd", - "publicKey": "01389197bbaf1afb0acd47bbfeabb34aca80fb372a8f694a1c0716b3398db746" - }, - { - "encryptedSecret": "f878b494a0917234af38fe71fbedd2b6e8a3382bd43b090243c3ce5ae9d3423b3f3f22fe54ff9752a921cebb5b2ae5319053a7907252d859c90855dd59419e6bea4eae2254be5e0b63f46bea670def99", - "publicKey": "aa33af13b440746b4f24312cba5fa910eb077ce6b16b84ebb482cb7720b5c686" - }, - { - "encryptedSecret": "f9b2c3470e4d0dfdccc2898f48beafab96678a3dc53c1d8f5ee26e2d21d2820d0d127e84e230280bf7983598a627c5e8c3a36b2de931cbfd5eb98086e25dd0df4b5ea86efbe8c07485c6c37bc2e650fa", - "publicKey": "6f04988de7e63537c8f14e84b0eb51e0ea9c5da8b4b9256243b3e40b1aeccb76" - }, - { - "encryptedSecret": "71fe042bb125a34edd0b2abda091f97e54cd80e17c38d52050334d4d41e59e0d62a294c05b1ea2737f1a65f160e6a10976da3ef8f9600ecfe0437562103566d6998c400aab7dbce69c0ccff39dd1a2e6", - "publicKey": "07935c642c7409c365258c8488760e96a851cee618aec72eeeb135c9c827f0f9" - }, - { - "encryptedSecret": "c857b847713b4fd4b42c0da416b62610cd1cbef635c9ecc2ae5386d691708e085695acad774c5166af2d0ffc821a7b442196b1f5ff6fc1b925169b38c9ca4066bb44cf600b0a3417b8162f238bb2fca8", - "publicKey": "526931663cbee883ff22369172cba091a5dd5fa1200284fa790d7aeca53d37af" - }, - { - "encryptedSecret": "00170536bc8d35142f094661ef2ab8b330bb29774ccc4473f10563e3ec5803a195da029f86ef95760c94ea7af4c9801723a86213f90505b14ac62be2b68297f1f5d222eae763fea7a67d1559f506bf94", - "publicKey": "f7b9751d59dd6be6029aa36a81a3f6436e2970cf4348845ab6254678fb946c18" - }, - { - "encryptedSecret": "eb75d9522694a83ecee93eddf3e935594e15f71fa9555cff68a8ea533fe861deea6d51ab874cfe0e06dd18fe6f26bfa4a1b419b37fd058bb2ef86a021299fc36c6395f8f6edbd2ebce9faf3737ab117d", - "publicKey": "5f6cc5a8aac752d37c676b0d46a798f7625e37dfa1e96091983274e04ab7ffe2" - }, - { - "encryptedSecret": "4b6fbff0e60bb77aa354ea03d79fa65e4639cf4a4a8a77179ca36a3012c963cfc770f36aba0304b87aca6753b2ee84e5cabfc67fc8be44be5f2c4c48bd4330bd2f57b04d2eae104f67e0ca63a365d5e8a33912a9f679b5f61631f60969c33457", - "publicKey": "9c16751dbe57f4dff7b3fb8911a62c0cb2bdee6240e3f3fefe76832788cb14c6" - }, - { - "encryptedSecret": "114932e16d3c19e1cbc7f75db9d854f352f513fb10b673d0cdf60c84d2f3d724acd6e35baaf0d8a84206575564dbbef9d8872ba8cbb3a05bab14d81ec4e5c339950489a01fc1497f2c1bc35ebc5dcd8a", - "publicKey": "ba2ea5e324eeb42fa6f4d1132a1d79911721e8507033bb0abd49715f531877b4" - }, - { - "encryptedSecret": "afee25e10519d0f6e30aa6988c6df49d15893536f48fcf7e4f55ac3b4cafd9d20ea79e55d8b77ec7eeeb6f95168a182c45842aff59064fc2dfe4841458ab84313164f59aff9d5771d07ec7575ad98d2c", - "publicKey": "0186d6cbee0c9b1a9783e7202f57fc234b1d98197ada1cc29cfbdf697a636ef1" - }, - { - "encryptedSecret": "5ffd4ce62804561cce6e29df22b2dd59d6ba165f342ad91d170f5b41f125d079ce691d364a59e2bd5b0e01db3f60f6046947a7ae66a131b9ff751246cbe5cd713370d2a2572edc73c82ffb2b50b3be25", - "publicKey": "edbb9828fbe62da2a59afbc8623e8ebc5ed2f9b7f77a0cd1cdcf55edea30521c" - }, - { - "encryptedSecret": "2fc83a3743527c1c94d167739a3d4e636a38023daec19b5f1f3054bd8a844e90ab437f14d47a1901e47088869365152cad7ae8e1b7a3f49611163e57cbf44d5911ba3767e3ef2d18e5e06bc8bbc8ee4f", - "publicKey": "b6ac700bf890b887e218dbd55b8f6b091dfc5a684d0fd7a6f69db7dc0313b51b" - }, - { - "encryptedSecret": "f620c283fad909e4450d87fdb255e7bb1b41977e3dfd7a8c6233294df032fb92de6e04043374ecf231f43df8277d75081810dbb24be8dd94aff2c0272f73d5065aa8526142db56c775304f121e967eaf", - "publicKey": "62bbb3c41e43df73de2c3f87e6577d095b84cf6deb1b2d6e87612a9156b980f8" - }, - { - "encryptedSecret": "56508d4e78b79390dc14be6631161b9435d3e598f96ced001e3f8cc958f14b96ca9640ea529e021e6cf94d8c97f7e5480d7bbe6e0de7404afe30c5d6c7889853261e7b77e3ad5a20b9e224fa705292dc", - "publicKey": "6fb2e0882cd9d895e1e441b9f9be7f98e877aa0a16ae230ee5caceb7a1b896ae" - }, - { - "encryptedSecret": "02a7c47f23bfb0ff058969a8a8ed8a2fe368b514179d6adf2374a6526d3ec849821b112ce9986c99803156d75775a1a43ae15ab63120c03f04e6360f8c9f0a8a498a148d413373908f015a30b00c9855", - "publicKey": "9a0f19e60581003b70291cf4a874e8217b04871e676b2c53c85a18ab95c2683b" - }, - { - "encryptedSecret": "4243f41e94c7f59c64907d0737dc6a26a1c01f42cbe547b49f61f0fd5694b56e283ae76a53743304e6155cca6af8f7c8a98a9489fc0076081122dbcec2e2d7f66fef6533c4049a5c8859214ca2fdb846", - "publicKey": "1e6ce18addd973ad432f05f16a4c86372eaca054cbdbcaf1169ad6df033f6b85" - }, - { - "encryptedSecret": "b181d7461e15d3e04e99d5c6ae6b3ac1894a4ff334febcf60453e3c08128fa515f87780cfcc7de9f154bc2639efea979d0bcaa9451d15a1fb1a3c573a3b9adeee6a417a14d4de1dcea8b93f09fff097a", - "publicKey": "27f43391cca75cbc82d1750307649508d1d318cd015f1f172b97318f17ab954e" - }, - { - "encryptedSecret": "ae0e1b12d9b2fe16f164f5a694707645117d4638ae9056117fc20f26fe377d1184bf4183c88c7d5a980dd5819cf38cdf675bcf3e4f590d06afdd4d1d040cffa96fb87b202e8cf21c7e5ab8d0540fc5ac", - "publicKey": "644a971f2c0d0d4b657d050fca27e5f9265e3dfa02a71f7fbf834cc2f2a6a4c8" - }, - { - "encryptedSecret": "2fd9d3b86e197fd49482107b643d9adcaf16fb75b32dc3c6795ad069e3406ef9cfc8bae161e9ab91c3bab2793af460f71e0485c951cf856e8797429afc303ecbd6b7bd4f013c81b899c981f742a553a0", - "publicKey": "cdd68a321ea737e82bce23d2208040f79471d36f2e6f84c74ea36ab26245e522" - }, - { - "encryptedSecret": "13f4c8b680c0d43e1ffa53c964325f1edbb40e5061b6a95d84ace18891364c7906d91aa12147fbc2c75d7f1a935337dd4091d29be832389165c0fea5f7ac3d6010ff9b733b03484a530c7c61edde5945", - "publicKey": "f9f6ff873c10c24eba834be28a56415a49c9c67b7c0ee9f106da827847168986" - }, - { - "encryptedSecret": "bd3300de753c603e2807e4691237a16419e7509d21014b508a3a02c635f5f0843f244875605a75c8fbbe00d2f5d8d00c2f58df6d8f1c3a6fb731e11028a020acb49cb1aae991cf5c182d7102bba8ce24", - "publicKey": "fab7b58be4c1e9542c342023b52e9d359ea89a3af34440bdb97318273e8555f0" - }, - { - "encryptedSecret": "a9a98f384a5d79d9032a458fa937777863d358ec99c63c938c47b37eb236bd3fe7982161263e6e277a6bce89bb71f943f7317d639fab1147e86599be451ed46cc025c84cc4cdd0afbb67728c1d6e6a731f4c8824bdfe0c9efac6c2cb82d18ddf", - "publicKey": "1b5a93c7622c666b0228236a70ee1a31407828b71bfb6daaa29a1509e87d4d3c" - }, - { - "encryptedSecret": "b551c1ab0ff78f6418d45fe53473e6f1edac1f9623199b0d7d1d618a798159f45a28f7cab7c9fec0f2288aac38c278845e813c02637a8af240b2dcacb79b71bc87967e8ac5ab9ce5e8d4880fb990c83d3a2117589a8a7c4ff16e850b66a3213b", - "publicKey": "74583aba9c0b92e4f08c8c75e6df341c255ca007971195ff64d6f909dc4b7177" - }, - { - "encryptedSecret": "0b1bb5f43def421b644904099112cf50255c55ce197b8672370b6f236713d2cb3e63f1537883dcc0e1337df5874d448670ea3cedf243379c4161e2223c682f27f7df3569bd82511fd1b5d8d10b96e64987dee45d657c407d798c127c423344b9", - "publicKey": "2b6f49383af36fd9f1a72d5d2708c8c354add89aaea7edc702c420e2d5fdf22e" - }, - { - "encryptedSecret": "898fa0b5b74f82a96c0209544f18f722e69afe986eb1f15b59c5f42ad5d74c89ee7adeb37f07ec08f1b0c08f1381e870e454bb00025a762320f734e70cadcb90af623ee3fb1c68a2c3e19698af609fe6", - "publicKey": "a10ed9c59dac2c4b8264dc34f2d318719fb5f20ecdd8d6be2d7abfe32294f20d" - }, - { - "encryptedSecret": "2b985f0d91b8afc47cbdd97baeb605dde3b43cf03ed508152c287fe81a6bcccf17fec260476bd1b666e34314a7c426c22d0912ec8f9ef51ef24e2fc4cc99b31a14aab7b4b93e7561428cfca7e4293904", - "publicKey": "c61d0822bbdbfe2a0b5503daff0ce8441c623115c94c0cfcf047a51f8b7160d3" - }, - { - "encryptedSecret": "f0a3b90500f90d25accae35247f1a9c31da915039415bd7457ff166d860efc217ac636712f3da910065277eb9594172d11250122be7d806279fddffa38516425dcc1ca0835110a0e8363faedd86ea10b", - "publicKey": "031e27beab583e2c94cb3167d128fc1a356c1ae88adfcfaa2334abffa3ae0b4c" - }, - { - "encryptedSecret": "c3ba451d1782554a7623b5fd05821322175b5dae5d37fabb4ddb1201ce12d6a89827847f6cf484f942cfcec8374471bfbf60015d140ef5bfea443d6d84d89484aff762812991e506101ce076ea6f504c", - "publicKey": "9986cedd4b5a28e4c81d9b4bff0461dddaa25099df00b8632fe99e88df28ce73" - }, - { - "encryptedSecret": "b690512b16387a0e8c676da57e8ec6ae941d6c9bb9bf411a75223eca7b5912f0ce26ecfd9e20bad87f2b2b437ac3a65ed107599e5309d440af190d0cdd964d08f4b8d556a74e7a3d313fa5f3d90d1abb", - "publicKey": "03e811dda4f51323ac712cd12299410830d655ddffb104f2c9974d90bf8c583a" - }, - { - "encryptedSecret": "106ab4fe7329b2b2305bad84cec475533538ad41b9834e4d8d7623a66f6d78dbc5c313e5e4c7023bfb0e62e76df70d74c0cf097de99d23030b9e76add43fe27bda98d5dc6569ef6e4a4d79f720227fcf", - "publicKey": "64db2bce729e302f6021047dfd39b6c53caf83b42da4b5b881cb153a3fb31613" - }, - { - "encryptedSecret": "dbdc922cdd7ebb7f34b1765ed49bfd3ad1602eeac08959fcf56235b9eb87ab156119990e4de1d4ee3817d735f861b5d57a378549fd084826ed6281d46cc27113a0e7f09d6f8e9116ca80f85d1d690444b7c32320f53c645dd93a01b579ebf0ee", - "publicKey": "f827f60366fae9f9ed65384979de780f4a18c6dbfbefb1c7d100957dde51a06d" - }, - { - "encryptedSecret": "8b020a97c8923d6c0f6478d8f4e107dc4144c6e06631c9ec6f400cfe35583af521149f03b3f93f2d3d11972afad0f3c464ee93cf42b4fbc2da618c03df4dd297c0e1e9a4d3e57df83736081f8cde1b4c", - "publicKey": "68680ca0bcd4676489976837edeac305c34f652e970386013ef26e67589a2516" - }, - { - "encryptedSecret": "14858db09f3c91ba1d593eb6629029b681738e2e0f900cfd8a02d4b272f24c932a02c640b04bf1454e9373b0864bc0ebdce685c4e7027ecf918a75ddc013c944144b39d316d33c94b06284ec4c62bcb7", - "publicKey": "f25af3c59ac7f5155c7a9f36762bd941b9dc9c5c051a1bc2d4e34ed773dd04a3" - }, - { - "encryptedSecret": "1e78d9f0c6df02fd0f3d4342fbb9a69b4ccd7ae19b4c34e1efea6ebb33055fb8661b2012b2a51ff37ff792e363375d8bc50d9632ca1456313cedf5632726000d1f6085c6a7b1af7522a8ec77e7e2452d", - "publicKey": "d3e3c8348bca51461eabfc382f8a01e8e284db54104ad37ec0695d48ae5531ac" - }, - { - "encryptedSecret": "8bf566f5535b678a71c3791de7e424385bf49b9b9ab89ca99305004cc17a557db3c9ea9b82b6a8874afd6e99ae642c41f4d2750efcdfbe06885f231c78c6289cf8e57807c0f86fdc683dcca37eca4b39", - "publicKey": "3be2eb47134d5158e5f7d52076b624b76744b3fba8aa50791b46ba21408524c9" - }, - { - "encryptedSecret": "841c73811a19a87413d971f11bed92f912c296a4602d4103aea9a632acdc583f0917a1cbd84bcd4b5b0eb0d216b1c0d7068c637099f1cacb11cd39738fc555e7de53a7aa181a0502c1fce60887abefa4a3ab119927d6e2e6228108c9b9f96d95", - "publicKey": "9f2fcc688518324273da230afff9756312bf23592174896fab669c2d78b1533c" - }, - { - "encryptedSecret": "c35c3b607292200a1a0f00b00c5b63bba049c873557189296667db63f212e1964afd2c9643de049f6257207340fb05f4de633929b540456f0f0672205a78ae1fb503760d40139a91cfff1ffa38f76856", - "publicKey": "e818ac2e8e9ffacd2d49f0f2f6739e16711644194d10bb1a8e9e434603125fa1" - }, - { - "encryptedSecret": "d9cf9f01f5d2a9674b679e97af437f4ca994b33eb7eaef246cecc584a3da1bc6b1af954a1a20ee8ae32f1eb0b2caf4f667ce14b418eb22348aa35ded35ae450b01734cf5ee3ac75e3b6bc75559a81148", - "publicKey": "19d55c023d85d6061d1e196fa440a50907878e2d425bcd893366fa04bc23b4de" - }, - { - "encryptedSecret": "9188d16f6ffcb204a2b2222b4d134c40a848a7220341a888f02482f18c2008b824d7e72832fa8ac8a894016c3e5c84236144021cf94b3f56d2f88a8155f6c8653803ee55cf641b3063483e1933f8745c", - "publicKey": "6d462852d410e84ca199a34d7ccad443784471f22cf3de37c531ce3b87ebbc41" - }, - { - "encryptedSecret": "2127f7e5cf7de58d4843d4871caaa200c8a421a629b59957e26c1bd2f49d74b51be231f1287dc06eb10b317a2dffeb62ead694b53d2551114ac795d94ec61c32ef81339edc2d93cf9b2cdbefe9a833b7", - "publicKey": "e6d075e3e396673c853210f74f8fe6db5e814c304bb9cd7f362018881a21f76c" - }, - { - "encryptedSecret": "98b2c027ab39e00c83f1fd097a787f71d39a3726f8afdb465ddc5e02def76058d9af6c455471a0af00b88358d6ca035b6aa354833356190332867aa8c58598be3dbebbcd4a477b3731256e2aa0d15561", - "publicKey": "0779ca873bbda77f2850965c8a3a3d40a6ee4ec56af55f0a3f16c7c34c0f298b" - }, - { - "encryptedSecret": "ef735fee1bf053c49d13c339163d66484700a784b4ce211624160c25b3876a3e37fb4ca4a931dcba359f423338574e43a62c92d812d078c3f07408c809f596654487899710f57ae8e7012eabb9f52a0b", - "publicKey": "73fec19d4bfe361c0680a7cfd24b3f744a1c1b29d932c4d89ce6157679f8af7d" - }, - { - "encryptedSecret": "e4f0a5a8580bf536196bb38d443a302374ce63ddc6ffc6487369af057818a781dc78a8ab00bf9c66de9dc241dfa3b5175594ccdf86a901a71969d6d4bf0b2884e0e0a5a63c793ca1f9c7bb87f1b0bd627f9f911d63218887e42414bb2d3ce811", - "publicKey": "1e82c7db09da2010e7f5fef24d83bc46238a20ef7ecdf12d9f32e4318a818777" - }, - { - "encryptedSecret": "b50a2013cb0f27eb6e75180094fff80328d3a28e89f99dae0d7ea84ed99a9d4bec9e7cb04207637af1f89a153408fe8d38e501ee6e0f08702486e5a31a6a251a41588e623df78617eb184022ebd86906", - "publicKey": "e42bfabc4a61f02131760af5f2fa0311007932a819a508da25f2ce6af2468156" - }, - { - "encryptedSecret": "4aef02c3564a17354ed8e292c6ea8b184137a6350f3a697a99bdf09dabe5674bc7939a0d4870545124fd08006a2c8399e8be1efbdb82fc6af0b0cafc0d4ee2e34c360ed1886c5d0970269f6ad3bdd951", - "publicKey": "bf9f5cfc548d29983cc0dfa5c4ec47c66c31df0f87aa669869678996902ab47f" - }, - { - "encryptedSecret": "56c5bf16c34d277cf9e70f5b1017a14bc42488f2ae293ec2fff65379381939606e1c0fe9b7876147c91a98957c6b2c62b5798ef554778b691b71826d81a54a119e2668f811436e3c4bd2f240cef7aa6e", - "publicKey": "b137de324fcc79dd1a21ae39a2ee8eed05e76b86d8e89d378f8bb766afb8719f" - }, - { - "encryptedSecret": "b9e8fe42467bd1a5b2c156f6c6f529e7c47943bcf5c67e8c31b8ff2954377e7035b29972ac4199e7e61ae53a48b1b360ffb0b6e3b13629d306842774253eaf937031f2e05ae538c04026a03574641fba", - "publicKey": "31402977c7eaf9e38d18d0689a45d719d615de941f7e80f6db388453b46f4df5" - }, - { - "encryptedSecret": "8741cb1bbfe2b801f0ef2faf43a1c7ba3899e93f4f64ad66707d9a7df21613b9483d8e915c9b15370ad5f7b073999823b6977ac90c10d47fed3618b9e4563e9ae6ca6278707755183ec62cb91daf0efd", - "publicKey": "f62062b7590d46f382fb8c37a26ab0a1bd512951777aedcaa96822230727d3a1" - }, - { - "encryptedSecret": "6a7c5a4b99eb340bbb554adb7d51ea4cac5e5047f1c7b80084dc5cd600a536b7311fecb41d5296278a85d2742b2a24b9aebb144fb244c3b3bb452180eef604ef3f0bf6b9cadd02539246c880a771f4972f9fdb13b3ca28a8cddbfa5895577e22", - "publicKey": "76c9494237e608d43fd6fb0114106a7517f5503cf79d7482db58a02304339b6c" - }, - { - "encryptedSecret": "8c639a2e1eb86b19644c820584d72ff5c6c896e633342b1ecc4c450f92d4cf7b6b143c6fc8b3be4fb85077028fd75197e17e46fe6f319bcffff7c9c8c2c13e77c24ef529d290f3c7632f0ae66b6111233bfad9fd99adff3f45f2ced65b0e9ef7", - "publicKey": "addb0e15a44b0fdc6ff291be28d8c98f5551d0cd9218d749e30ddb87c6e31ca9" - }, - { - "encryptedSecret": "47f7103ecc7c7d1678e311533632fe970b9f85ab32f22ace7be420c46f3a4926f3d29ab6c2e33df3f2160965c4109c72474503f3db45076a03e43c3024c7ad00fc312022b599bac6893f2a6770b80e69", - "publicKey": "904c294899819cce0283d8d351cb10febfa0e9f0acd90a820ec8eb90a7084c37" - } - ], - "access": { - "whiteList": [ - "127.0.0.1" - ] - } - }, - "loading": { - "verifyOnLoading": false, - "loadPerIteration": 5000 - }, - "ssl": { - "enabled": false, - "options": { - "port": 443, - "address": "0.0.0.0", - "key": "./ssl/lisk.key", - "cert": "./ssl/lisk.crt" - } - }, - "nethash": "198f2b61a8eb95fbeed58b8216780b68f697f26b849acf00c8c93bb9b24f783d" + "options": { + "limits": { + "max": 0, + "delayMs": 0, + "delayAfter": 0, + "windowMs": 60000 + }, + "timeout": 5000 + } + }, + "broadcasts": { + "broadcastInterval": 5000, + "broadcastLimit": 20, + "parallelLimit": 20, + "releaseLimit": 25, + "relayLimit": 2 + }, + "transactions": { + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInterval": 25000 + } + }, + "forging": { + "force": false, + "secret": [], + "access": { + "whiteList": [ + "127.0.0.1" + ] + } + }, + "loading": { + "verifyOnLoading": false, + "loadPerIteration": 5000 + }, + "ssl": { + "enabled": false, + "options": { + "port": 443, + "address": "0.0.0.0", + "key": "./ssl/lisk.key", + "cert": "./ssl/lisk.crt" + } + }, + "nethash": "ed14889723f24ecc54871d058d98ce91ff2f973192075c0155ba2b7b70ad2511" } From 01ef3323ffc552a7daa80fe10638aae065f0dbc2 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 30 Oct 2017 13:56:36 +0100 Subject: [PATCH 47/86] Test getReady with transaction limit --- test/unit/logic/transactions/pool.js | 35 ++++++++++++++++++---------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 498d0a5b60b..d2798647cbe 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -1053,7 +1053,7 @@ describe('transactionPool', function () { describe('by pool list', function () { it('should be ok when check pool list unverified', function (done) { - var transactions = transactionPool.getAll('unverified', { limit: null }); + var transactions = transactionPool.getAll('unverified', {limit: null}); expect(Object.keys(transactions).length).to.equal(2); done(); @@ -1067,35 +1067,35 @@ describe('transactionPool', function () { }); it('should be ok when check pool list pending', function (done) { - var transactions = transactionPool.getAll('pending', { limit: null }); + var transactions = transactionPool.getAll('pending', {limit: null}); expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list pending with limit', function (done) { - var transactions = transactionPool.getAll('pending', { limit: 1 }); + var transactions = transactionPool.getAll('pending', {limit: 1}); expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list ready', function (done) { - var transactions = transactionPool.getAll('ready', { limit: null }); + var transactions = transactionPool.getAll('ready', {limit: null}); expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should be ok when check pool list ready with limit', function (done) { - var transactions = transactionPool.getAll('ready', { limit: 1 }); + var transactions = transactionPool.getAll('ready', {limit: 1}); expect(Object.keys(transactions).length).to.equal(1); done(); }); it('should fail when filter is invalid', function (done) { - var transactions = transactionPool.getAll('unknown', { limit: null }); + var transactions = transactionPool.getAll('unknown', {limit: null}); expect(transactions).to.equal('Invalid filter'); done(); @@ -1105,7 +1105,7 @@ describe('transactionPool', function () { describe('by id (address) and publicKey', function () { it('should be ok when sender account is valid', function (done) { - var transactions = transactionPool.getAll('sender_id', { id: '2737453412992791987L' }); + var transactions = transactionPool.getAll('sender_id', {id: '2737453412992791987L'}); expect(transactions.unverified.length).to.equal(1); expect(transactions.pending.length).to.equal(0); @@ -1114,7 +1114,7 @@ describe('transactionPool', function () { }); it('should be ok when recipient account is valid', function (done) { - var transactions = transactionPool.getAll('recipient_id', { id: '2737453412992791987L' }); + var transactions = transactionPool.getAll('recipient_id', {id: '2737453412992791987L'}); expect(transactions.unverified.length).to.equal(1); expect(transactions.pending.length).to.equal(0); @@ -1123,7 +1123,7 @@ describe('transactionPool', function () { }); it('should be ok when sender publicKey is valid', function (done) { - var transactions = transactionPool.getAll('sender_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + var transactions = transactionPool.getAll('sender_pk', {publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'}); expect(transactions.unverified.length).to.equal(1); expect(transactions.pending.length).to.equal(1); @@ -1132,7 +1132,7 @@ describe('transactionPool', function () { }); it('should be ok when requester publicKey is valid', function (done) { - var transactions = transactionPool.getAll('recipient_pk', { publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8' }); + var transactions = transactionPool.getAll('recipient_pk', {publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'}); expect(transactions.unverified.length).to.equal(1); expect(transactions.pending.length).to.equal(0); @@ -1242,7 +1242,7 @@ describe('transactionPool', function () { }); it('should be ok when add type 2 transaction again to ready', function (done) { - transactionPool.addReady(transactions[2], function (err, cbtransaction) { + transactionPool.addReady(allTransactions[2], function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -1258,6 +1258,17 @@ describe('transactionPool', function () { done(); }); + it('should be ok when get transactions from ready with limit', function (done) { + var readyTransactions = transactionPool.getReady(2); + + expect(readyTransactions.length).to.equal(2); + expect(readyTransactions[0].receivedAt).to.not.equal(readyTransactions[1].receivedAt); + expect(readyTransactions[1].receivedAt).to.equal(readyTransactions[2].receivedAt); + expect(readyTransactions[2].receivedAt).to.equal(readyTransactions[3].receivedAt); + expect(readyTransactions[3].receivedAt).to.equal(readyTransactions[4].receivedAt); + done(); + }); + it('should be ok when delete transaction from ready', function (done) { var deleteTransaction = transactionPool.delete(transactions[0]); @@ -1307,7 +1318,7 @@ describe('transactionPool', function () { describe('checkBalance', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { - transactionPool.checkBalance(transactions[0], { address: transactions[0].senderId }, function (err, cbBalance) { + transactionPool.checkBalance(transactions[0], {address: transactions[0].senderId}, function (err, cbBalance) { expect(cbBalance).to.equal('balance: 52999994'); done(); }); From 941dbeada3349e35cdbcfb70c3397714bb0462a3 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 31 Oct 2017 16:58:38 +0100 Subject: [PATCH 48/86] Speedup function with some instead of filter --- logic/transactions/pool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index d358985210d..e5b0b037144 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -150,9 +150,9 @@ __private.transactionInPool = function (id) { pool.unverified.transactions[id], pool.verified.pending.transactions[id], pool.verified.ready.transactions[id] - ].filter(function (inList) { - return inList !== undefined; - }).length > 0; + ].some(function (index) { + return typeof(index) === 'number'; + }); }; /** From ec96e38c574e05318398f1aeeb08348eb3c6ac42 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 1 Nov 2017 16:50:54 +0100 Subject: [PATCH 49/86] Include broadcast field into test method add --- test/unit/logic/transactions/pool.js | 90 ++++++++++++++-------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index d2798647cbe..858eaa0768c 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -272,20 +272,20 @@ describe('transactionPool', function () { done(); }); - describe('processPool', function () { + describe('processPool - no broadcast', function () { describe('Transaction type: 0 - Transmit funds', function () { var tmpTransactionInvalidId; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[0], function (err, cbtransaction) { + transactionPool.add(transactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[0], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -295,7 +295,7 @@ describe('transactionPool', function () { tmpTransactionInvalidId = _.cloneDeep(invalidsTransactions[0]); tmpTransactionInvalidId.id = '01234567890123456789'; - transactionPool.add(tmpTransactionInvalidId, function (err, cbtransaction) { + transactionPool.add(tmpTransactionInvalidId, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -314,14 +314,14 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[0], function (err, cbtransaction) { + transactionPool.add(transactions[0], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); done(); }); }); it('should fail when add same transaction with invalid id to unverified', function (done) { - transactionPool.add(tmpTransactionInvalidId, function (err, cbtransaction) { + transactionPool.add(tmpTransactionInvalidId, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTransactionInvalidId.id); done(); }); @@ -360,14 +360,14 @@ describe('transactionPool', function () { var invalidTransactionType; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[1], function (err, cbtransaction) { + transactionPool.add(transactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -378,7 +378,7 @@ describe('transactionPool', function () { invalidTransactionType.id = '12345678901234567890'; invalidTransactionType.type = 99; - transactionPool.add(invalidTransactionType, function (err, cbtransaction) { + transactionPool.add(invalidTransactionType, false, function (err, cbtransaction) { if (err) { done(err); } @@ -400,14 +400,14 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[1], function (err, cbtransaction) { + transactionPool.add(transactions[1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); done(); }); }); it('should fail when add same transaction with invalid transaction type to unverified', function (done) { - transactionPool.add(invalidTransactionType, function (err, cbtransaction) { + transactionPool.add(invalidTransactionType, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidTransactionType.id); done(); }); @@ -446,28 +446,28 @@ describe('transactionPool', function () { var invalidSignature; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[2], function (err, cbtransaction) { + transactionPool.add(transactions[2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[2][0], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that already is a delegate', function (done) { - transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with same username', function (done) { - transactionPool.add(invalidsTransactions[2][2], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -476,7 +476,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, function (err, cbtransaction) { + transactionPool.add(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -499,35 +499,35 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[2], function (err, cbtransaction) { + transactionPool.add(transactions[2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with same username to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][2], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][2].id); done(); }); }); it('should fail when add same transaction with invalid signature to unverified', function (done) { - transactionPool.add(invalidSignature, function (err, cbtransaction) { + transactionPool.add(invalidSignature, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidSignature.id); done(); }); @@ -565,21 +565,21 @@ describe('transactionPool', function () { describe('Transaction type: 3 - Submit votes', function () { it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[3], function (err, cbtransaction) { + transactionPool.add(transactions[3], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[3][0], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[3][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that votes a non delegate', function (done) { - transactionPool.add(invalidsTransactions[3][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -598,14 +598,14 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[3], function (err, cbtransaction) { + transactionPool.add(transactions[3], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); done(); }); }); it('should fail when add same transaction that votes a non delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[3][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[3][1].id); done(); }); @@ -647,14 +647,14 @@ describe('transactionPool', function () { it('should be ok when add normal transaction to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, function (err, cbtransaction) { + transactionPool.add(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not register signer in database', function (done) { - transactionPool.add(transactions[4][1], function (err, cbtransaction) { + transactionPool.add(transactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -663,21 +663,21 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[4][0], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[4][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with invalid signeer', function (done) { - transactionPool.add(invalidsTransactions[4][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -697,21 +697,21 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(completedSignatures, function (err, cbtransaction) { + transactionPool.add(completedSignatures, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + completedSignatures.id); done(); }); }); it('should fail when add same transaction with unregister signer to unverified', function (done) { - transactionPool.add(transactions[4][1], function (err, cbtransaction) { + transactionPool.add(transactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[4][1].id); done(); }); }); it('should fail when add same transaction without enough signatures to unverified', function (done) { - transactionPool.add(invalidsTransactions[4][1], function (err, cbtransaction) { + transactionPool.add(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[4][1].id); done(); }); @@ -826,7 +826,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, function (err, cbtransaction) { + transactionPool.add(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -835,7 +835,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, function (err, cbtransaction) { + transactionPool.add(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -844,7 +844,7 @@ describe('transactionPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -864,7 +864,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - transactionPool.add(normalTransaction, function (err, cbtransaction) { + transactionPool.add(normalTransaction, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -957,7 +957,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, function (err, cbtransaction) { + transactionPool.add(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -966,7 +966,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, function (err, cbtransaction) { + transactionPool.add(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -975,7 +975,7 @@ describe('transactionPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, function (err, cbtransaction) { + transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -995,7 +995,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - transactionPool.add(normalTransaction, function (err, cbtransaction) { + transactionPool.add(normalTransaction, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -1005,7 +1005,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 3 to unverified', function (done) { var normalTransactionT3 = _.cloneDeep(transactions[3]); normalTransactionT3.requesterPublicKey = '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'; - transactionPool.add(normalTransactionT3, function (err, cbtransaction) { + transactionPool.add(normalTransactionT3, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -1156,7 +1156,7 @@ describe('transactionPool', function () { transactions.push(e); } }); - transactionPool.add(transactions, function (err, cbtransaction) { + transactionPool.add(transactions, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; expect(err).to.equal('Transaction pool is full'); done(); @@ -1174,7 +1174,7 @@ describe('transactionPool', function () { it('should fail when add transaction and pool storage is full', function (done) { var extraTransaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret); - transactionPool.add(extraTransaction, function (err, cbtransaction) { + transactionPool.add(extraTransaction, false, function (err, cbtransaction) { expect(err).to.equal('Transaction pool is full'); done(); }); From 53ca5c33bfae0f7210e72e18e199cc211fab7330 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 15 Nov 2017 11:55:59 +0100 Subject: [PATCH 50/86] Get config options from file --- logic/transactions/pool.js | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e5b0b037144..c643244020b 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -26,17 +26,14 @@ var pool = {}; * @implements {processPool} * @implements {expireTransactions} * @implements {resetInvalidTransactions} - * @param {number} storageLimit - * @param {number} processInterval - * @param {number} expiryInterval - * @param {Transaction} transaction - Logic instance - * @param {Account} account - Account instance - * @param {bus} bus * @param {Object} logger + * @param {bus} bus * @param {Object} ed + * @param {Transaction} transaction - transaction logic instance + * @param {Account} account - account logic instance */ // Constructor -function TransactionPool (storageLimit, processInterval, expiryInterval, transaction, account, bus, logger, ed) { +function TransactionPool (bus, ed, transaction, account, logger, configPool, cbPool) { library = { logger: logger, bus: bus, @@ -48,9 +45,9 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac config: { transactions: { pool: { - storageLimit: storageLimit, - processInterval: processInterval, - expiryInterval: expiryInterval + storageLimit: configPool.storageLimit, + processInterval: configPool.processInterval, + expiryInterval: configPool.expiryInterval } } }, @@ -100,6 +97,10 @@ function TransactionPool (storageLimit, processInterval, expiryInterval, transac } jobsQueue.register('transactionPoolNextReset', nextReset, self.poolExpiryInterval); + + if (cbPool) { + return setImmediate(cbPool, null, self); + } } @@ -222,6 +223,7 @@ __private.addToUnverified = function (transaction, broadcast, cb) { if (broadcast) { transaction.broadcast = true; } + transaction.receivedAt = new Date(); pool.unverified.transactions[transaction.id] = transaction; pool.unverified.count++; } @@ -246,16 +248,15 @@ __private.addToPoolList = function (transaction, poolList, cb) { /** * Adds transactions to pool list without checks. * @param {transaction} transaction - * @param {Object} poolList * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -__private.addReadyCeckBroadcast = function (transaction, poolList, cb) { +__private.addReadyCheckBroadcast = function (transaction, cb) { if (transaction.broadcast) { delete transaction.broadcast; pool.broadcast.push(transaction); } - return __private.addToPoolList(transaction, pool.verified.ready, cb); + __private.addToPoolList(transaction, pool.verified.ready, cb); }; /** @@ -509,7 +510,10 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { if (err) { return setImmediate(cb, err); } - + if (account === null) { + account = {}; + account.balance = 0; + } // total payments paymentTransactions = self.getAll('sender_id', { id: sender.address }); if (paymentTransactions.ready.length > 0) { @@ -564,8 +568,8 @@ TransactionPool.prototype.add = function (transactions, broadcast, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } - async.eachSeries(transactions, function (transaction, broadcast, eachSeriesCb) { - __private.addToUnverified(transaction, broadcast, eachSeriesCb); + async.eachSeries(transactions, function (transaction, cb) { + __private.addToUnverified(transaction, broadcast, cb); }, function (err) { return setImmediate(cb, err); }); @@ -676,7 +680,6 @@ TransactionPool.prototype.processPool = function (cb) { library.logger.error('Failed to check balance transaction: ' + transaction.id, err); return setImmediate(eachSeriesCb); } - transaction.receivedAt = new Date(); var receiveAtToTime = transaction.receivedAt.getTime(); var timestampToTime = slots.getRealTime(transaction.timestamp); if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { From c3a44e5088fd0312551440f43366315fade1ed89 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 6 Nov 2017 17:57:56 +0100 Subject: [PATCH 51/86] Improve pool to addFromPeer and addFromPublic --- logic/transactions/pool.js | 319 ++++++++++++++++++++++++++++--------- 1 file changed, 246 insertions(+), 73 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index c643244020b..5f17e229193 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -143,97 +143,246 @@ __private.getAllPoolTransactionsByFilter = function (filter) { /** * Returns true if the id is present in at least one of the pool lists transactions. + * @private * @param {string} id * @return {boolean} */ __private.transactionInPool = function (id) { return [ + pool.verified.ready.transactions[id], pool.unverified.transactions[id], - pool.verified.pending.transactions[id], - pool.verified.ready.transactions[id] + pool.verified.pending.transactions[id] ].some(function (index) { - return typeof(index) === 'number'; + return typeof(index) === 'object'; }); }; /** - * Adds transactions to unverified pool list. - * Checks if transaction is in pool, pool limit and performs basic transaction validations. + * Checks if pool is ready to receive a new transaction and the incoming + * transaction was not already processed by pool. + * @private * @implements {__private.countTransactionsPool} * @implements {__private.transactionInPool} - * @param {Transaction} transaction - * @param {boolean} broadcast + * @param {Object} transaction * @param {function} cb - Callback function. - * @return {setImmediateCallback} error | cb + * @return {setImmediateCallback} error | cb, transaction */ -__private.addToUnverified = function (transaction, broadcast, cb) { +__private.checkPoolAvailability = function (transaction, waterCb) { if (__private.countTransactionsPool() >= self.poolStorageTransactionsLimit) { - return setImmediate(cb, 'Transaction pool is full'); + return setImmediate(waterCb, 'Transaction pool is full'); } if (pool.invalid.transactions[transaction.id] !== undefined) { - return setImmediate(cb, 'Transaction is already processed as invalid: ' + transaction.id); + return setImmediate(waterCb, 'Transaction is already processed as invalid: ' + transaction.id); } if (__private.transactionInPool(transaction.id)) { - return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); + return setImmediate(waterCb, 'Transaction is already in pool: ' + transaction.id); + } + return setImmediate(waterCb, null, transaction); +}; + +/** + * Obtains sender from accounts table, if address does not exists, + * returns a default account object. + * @private + * @implements {modules.accounts.setAccountAndGet} + * @param {Object} transaction + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb, transaction, sender + */ +__private.setAccountAndGet = function (transaction, waterCb) { + modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, function (err, cb) { + return setImmediate(waterCb, err, transaction, cb); + }); +}; + +/** + * Obtains requester from accounts table + * @private + * @implements {modules.accounts.getAccount} + * @param {Object} transaction + * @param {Object} sender + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb, transaction, sender, requester + */ +__private.getRequester = function (transaction, sender, waterCb) { + var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; + + if (multisignatures) { + transaction.signatures = transaction.signatures || []; + } + + if (sender && transaction.requesterPublicKey && multisignatures) { + modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { + if (!requester) { + return setImmediate(waterCb, 'Requester not found'); + } else { + return setImmediate(waterCb, null, transaction, sender, requester); + } + }); } else { - async.waterfall([ - function setAccountAndGet (waterCb) { - modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); - }, - function getRequester (sender, waterCb) { - var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; - - if (multisignatures) { - transaction.signatures = transaction.signatures || []; - } - - if (sender && transaction.requesterPublicKey && multisignatures) { - modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { - if (!requester) { - return setImmediate(waterCb, 'Requester not found'); - } else { - return setImmediate(waterCb, null, sender, requester); - } - }); - } else { - return setImmediate(waterCb, null, sender, null); - } - }, - function processTransaction (sender, requester, waterCb) { - library.logic.transaction.process(transaction, sender, requester, function (err) { - if (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, sender); - } - }); - }, - function normalizeTransaction (sender, waterCb) { - try { - transaction = library.logic.transaction.objectNormalize(transaction); - return setImmediate(waterCb, null, sender); - } catch (err) { - __private.addInvalid(transaction.id); + return setImmediate(waterCb, null, transaction, sender, null); + } +}; + +/** + * Process transaction. + * @private + * @implements {library.logic.transaction.process} + * @implements {__private.addInvalid} + * @param {Object} transaction + * @param {Object} sender + * @param {Object} requester + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb, transaction, sender + */ +__private.processTransaction = function (transaction, sender, requester, waterCb) { + library.logic.transaction.process(transaction, sender, requester, function (err) { + if (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err); + } + return setImmediate(waterCb, null, transaction, sender); + }); +}; + +/** + * Normalizes transaction. + * @private + * @implements {library.logic.transaction.objectNormalize} + * @implements {__private.addInvalid} + * @param {Object} transaction + * @param {Object} sender + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb, transaction, sender + */ +__private.normalizeTransaction = function (transaction, sender, waterCb) { + try { + transaction = library.logic.transaction.objectNormalize(transaction); + return setImmediate(waterCb, null, transaction, sender); + } catch (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err, null); + } +}; + +/** + * Verifyes transaction. + * @private + * @implements {library.logic.transaction.verify} + * @implements {__private.addInvalid} + * @param {Object} transaction + * @param {Object} sender + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb, transaction, sender + */ +__private.verifyTransaction = function (transaction, sender, waterCb) { + library.logic.transaction.verify(transaction, sender, function (err) { + if (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, transaction, sender); + } + }); +}; + +/** + * Adds transaction to verify pending or ready. + * @private + * @implements {__private.addToPoolList} + * @implements {__private.addReadyCheckBroadcast} + * @param {Object} transaction + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.moveToVerified = function (transaction, cb) { + var receiveAtToTime = transaction.receivedAt.getTime(); + var timestampToTime = slots.getRealTime(transaction.timestamp); + if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { + __private.addToPoolList(transaction, pool.verified.pending, cb); + } else { + __private.addReadyCheckBroadcast(transaction, cb); + } +}; + +/** + * Adds transactions to verified pool list. + * Checks if transaction is in pool, pool limit, performs basic transaction validations + * and advanced transaction validations: verify and check balance. + * @private + * @implements {__private.checkPoolAvailability} + * @implements {__private.setAccountAndGet} + * @implements {__private.getAccount} + * @implements {__private.processTransaction} + * @implements {__private.normalizeTransaction} + * @implements {__private.verifyTransaction} + * @implements {__private.moveToVerified} + * @param {Transaction} transaction + * @param {boolean} broadcast + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.addToVerified = function (transaction, broadcast, cb) { + transaction.receivedAt = new Date(); + async.waterfall([ + async.apply(__private.checkPoolAvailability, transaction), + __private.setAccountAndGet, + __private.getRequester, + __private.processTransaction, + __private.normalizeTransaction, + __private.verifyTransaction, + function checkBalance (transaction, sender, waterCb) { + self.checkBalance(transaction, sender, function (err, balance) { + if (err) { return setImmediate(waterCb, err); } + return __private.moveToVerified(transaction, waterCb); + }); + } + ], function (err) { + return setImmediate(cb, err); + }); + +}; + +/** + * Adds transactions to unverified pool list. + * Checks if transaction is in pool, pool limit and performs basic transaction validations. + * @private + * @implements {__private.checkPoolAvailability} + * @implements {__private.setAccountAndGet} + * @implements {__private.getAccount} + * @implements {__private.processTransaction} + * @implements {__private.normalizeTransaction} + * @param {Transaction} transaction + * @param {boolean} broadcast + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +__private.addToUnverified = function (transaction, broadcast, cb) { + async.waterfall([ + async.apply(__private.checkPoolAvailability, transaction), + __private.setAccountAndGet, + __private.getRequester, + __private.processTransaction, + __private.normalizeTransaction + ], function (err, transaction, sender) { + if (!err) { + if (broadcast) { + transaction.broadcast = true; } - ], function (err, sender) { - if (!err) { - if (broadcast) { - transaction.broadcast = true; - } - transaction.receivedAt = new Date(); - pool.unverified.transactions[transaction.id] = transaction; - pool.unverified.count++; - } - return setImmediate(cb, err, sender); - }); - } + transaction.receivedAt = new Date(); + pool.unverified.transactions[transaction.id] = transaction; + pool.unverified.count++; + } + return setImmediate(cb, err, transaction); + }); + }; /** * Adds transactions to pool list without checks. + * @private * @param {transaction} transaction * @param {Object} poolList * @param {function} cb - Callback function. @@ -247,6 +396,7 @@ __private.addToPoolList = function (transaction, poolList, cb) { /** * Adds transactions to pool list without checks. + * @private * @param {transaction} transaction * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb @@ -281,6 +431,7 @@ __private.createSignature = function (transaction, secret, cb) { /** * Adds transaction id to invalid pool list. + * @private * @param {string} id */ __private.addInvalid = function (id) { @@ -290,6 +441,7 @@ __private.addInvalid = function (id) { /** * Deletes id from pool list. + * @private * @param {string} id * @param {Object} poolList * @return {boolean} true if transaction id is on the list and was deleted @@ -307,6 +459,7 @@ __private.delete = function (id, poolList) { /** * Sums unverified, verified.pending and verified.ready counters. + * @private * @return {Number} Total = unverified + pending + ready */ __private.countTransactionsPool = function () { @@ -556,6 +709,18 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { }); }; +/** + * Validates a transaction and adds it to the verified pool list. + * @implements {__private.addToVerified} + * @param {transaction} transaction + * @param {boolean} broadcast + * @param {function} cb - Callback function. + * @return {setImmediateCallback} error | cb + */ +TransactionPool.prototype.addFromPublic = function (transaction, broadcast, cb) { + __private.addToVerified(transaction, broadcast, cb); +}; + /** * Adds transactions to unverified pool list. * @implements {__private.addToUnverified} @@ -564,7 +729,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -TransactionPool.prototype.add = function (transactions, broadcast, cb) { +TransactionPool.prototype.addFromPeer = function (transactions, broadcast, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } @@ -651,13 +816,27 @@ TransactionPool.prototype.delete = function (id) { return clearedList; }; +/** + * Deletes transactions from pool lists and rechecks balance for ready transactions + * @implements {__private.delete} + * @param {string} id transaction id + * @return {Array} names of cleared lists + */ +TransactionPool.prototype.sanitizeTransactions = function (transactions) { + transactions.forEach(function (transaction) { + self.delete(transaction.id); + }); +}; + /** * Pulls transactions from unverified, perform verifications and if successful * push to either verified.pending (when transaction is multisign or timestamp is in * future) or verified.ready otherwise. * @implements {__private.delete} - * @implements {processVerifyTransaction} - * @implements {removeUnconfirmedTransaction} + * @implements {__private.processUnverifiedTransaction} + * @implements {self.checkBalance} + * @implements {__private.moveToVerified} + * @implements {__private.addReadyCheckBroadcast} * @param {function} cb * @return {setImmediateCallback} err | cb */ @@ -680,13 +859,7 @@ TransactionPool.prototype.processPool = function (cb) { library.logger.error('Failed to check balance transaction: ' + transaction.id, err); return setImmediate(eachSeriesCb); } - var receiveAtToTime = transaction.receivedAt.getTime(); - var timestampToTime = slots.getRealTime(transaction.timestamp); - if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { - __private.addToPoolList(transaction, pool.verified.pending, eachSeriesCb); - } else { - __private.addReadyCheckBroadcast(transaction, eachSeriesCb); - } + return __private.moveToVerified(transaction, eachSeriesCb); }); }); }, function (err) { From 446732514b41186b36cd5e8e74957577a1b1dda7 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 6 Nov 2017 18:16:27 +0100 Subject: [PATCH 52/86] Add forge function, change calls to use addFromPublic --- test/unit/logic/transactions/pool.js | 323 +++++++++++++++++---------- 1 file changed, 202 insertions(+), 121 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 858eaa0768c..61788ba661b 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -3,6 +3,8 @@ var expect = require('chai').expect; var sinon = require('sinon'); var _ = require('lodash'); +var rewire = require('rewire'); +var slots = require('../../../../helpers/slots.js'); var node = require('../../../node'); var DBSandbox = require('../../../common/globalBefore').DBSandbox; @@ -137,25 +139,22 @@ var hackedTransactions = [ ]; // Set spies for logger -var debug = sinon.stub(modulesLoader.scope.logger, 'debug'); -var info = sinon.stub(modulesLoader.scope.logger, 'info'); -var warn = sinon.stub(modulesLoader.scope.logger, 'warn'); -var error = sinon.stub(modulesLoader.scope.logger, 'error'); +var logger; function resetSpiesState () { // Reset state of spies - debug.reset(); - info.reset(); - warn.reset(); - error.reset(); + logger.debug.reset(); + logger.info.reset(); + logger.warn.reset(); + logger.error.reset(); } function restoreSpiesState () { // Restore state of spies - debug.restore(); - info.restore(); - warn.restore(); - error.restore(); + logger.debug.restore(); + logger.info.restore(); + logger.warn.restore(); + logger.error.restore(); } function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { @@ -170,8 +169,8 @@ function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgro } describe('transactionPool', function () { - - var accounts; + + var library; var transactionPool; var poolTotals; var poolStorageTransactionsLimit; @@ -183,15 +182,15 @@ describe('transactionPool', function () { if (err) { return done(err); } + + constants.unconfirmedTransactionTimeOut = 1; + constants.signatureTransactionTimeOutMultiplier = 1; + constants.secondsPerHour = 1; + poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; + modulesLoader.scope.config.transactions.pool.processInterval = 60000000; + modulesLoader.scope.config.transactions.pool.expiryInterval = 80000000; // Wait for genesisBlock transaction being applied node.initApplication(function (err, scope) { - constants.unconfirmedTransactionTimeOut = 1; - constants.signatureTransactionTimeOutMultiplier = 1; - constants.secondsPerHour = 1; - poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; - modulesLoader.scope.config.transactions.pool.processInterval = 60000000; - modulesLoader.scope.config.transactions.pool.expiryInterval = 300000000; - // Init transaction logic transactionPool = new TransactionPool( modulesLoader.scope.config.transactions.pool.storageLimit, @@ -208,7 +207,8 @@ describe('transactionPool', function () { null, scope.modules.loader ); - accounts = scope.modules.accounts; + library = scope; + logger = scope.logger; done(); }, {db: __db}); }); @@ -227,35 +227,121 @@ describe('transactionPool', function () { node.appCleanup(done); }); - describe('setup database', function () { + function forge (cb) { + function getNextForger (offset, cb) { + offset = !offset ? 1 : offset; + var last_block = library.modules.blocks.lastBlock.get(); + var slot = slots.getSlotNumber(last_block.timestamp); + // TODO: wait 0.9.10 backport to 1.0.0 to get delegate list + //library.modules.delegates.generateDelegateList(last_block.height, null, function (err, delegateList) { + library.modules.delegates.generateDelegateList(function (err, delegateList) { + if (err) { return cb (err); } + var nextForger = delegateList[(slot + offset) % slots.delegates]; + return cb(nextForger); + }); + } - it('should be ok when generate account 1', function (done) { - accounts.setAccountAndGet(testAccounts[0].account, function (err, newaccount) { - expect(newaccount.address).to.equal(testAccounts[0].account.address); + var loadDelegates = library.rewiredModules.delegates.__get__('__private.loadDelegates'); + + node.async.waterfall([ + loadDelegates, + transactionPool.processPool, + function (cb) { + getNextForger(null, function (delegatePublicKey) { + cb(null, delegatePublicKey); + }); + }, + function (delegate, seriesCb) { + var keypairs = library.rewiredModules.delegates.__get__('__private.keypairs'); + var last_block = library.modules.blocks.lastBlock.get(); + var slot = slots.getSlotNumber(last_block.timestamp) + 1; + var keypair = keypairs[delegate]; + node.debug(' Last block height: ' + last_block.height + ' Last block ID: ' + last_block.id + ' Last block timestamp: ' + last_block.timestamp + ' Next slot: ' + slot + ' Next delegate PK: ' + delegate + ' Next block timestamp: ' + slots.getSlotTime(slot)); + library.modules.blocks.process.generateBlock(keypair, slots.getSlotTime(slot), function (err) { + if (err) { return seriesCb(err); } + last_block = library.modules.blocks.lastBlock.get(); + node.debug(' New last block height: ' + last_block.height + ' New last block ID: ' + last_block.id); + return seriesCb(err); + }); + } + ], function (err) { + cb(err); + }); + } + + describe('setup database', function () { + var transaction; + var totalDB; + + it('should be ok when add account 1 transaction to unverified', function (done) { + transaction = node.lisk.transaction.createTransaction(testAccounts[0].account.address, testAccounts[0].account.balance, node.gAccount.password); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when generate account 2', function (done) { - accounts.setAccountAndGet(testAccounts[1].account, function (err, newaccount) { - expect(newaccount.address).to.equal(testAccounts[1].account.address); + it('should be ok when add account 2 transaction to unverified', function (done) { + transaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, testAccounts[1].account.balance, node.gAccount.password); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when generate account 3', function (done) { - accounts.setAccountAndGet(testAccounts[2].account, function (err, newaccount) { - expect(newaccount.address).to.equal(testAccounts[2].account.address); + it('should be ok when add account 3 transaction to unverified', function (done) { + transaction = node.lisk.transaction.createTransaction(testAccounts[2].account.address, testAccounts[2].account.balance, node.gAccount.password); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when generate account 4', function (done) { - accounts.setAccountAndGet(testAccounts[3].account, function (err, newaccount) { - expect(newaccount.address).to.equal(testAccounts[3].account.address); + it('should be ok when add account 4 transaction to unverified', function (done) { + transaction = node.lisk.transaction.createTransaction(testAccounts[3].account.address, testAccounts[3].account.balance, node.gAccount.password); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; done(); }); }); + + it('should be ok when get pool totals to initialize local counter', function (done) { + var totals = transactionPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.a('number'); + expect(totals.pending).to.be.a('number'); + expect(totals.ready).to.be.a('number'); + expect(totals.invalid).to.be.a('number'); + totalDB = totals; + done(); + }); + + it('should be ok when process transactions and create blocks', function (done) { + setTimeout(function () { + forge(function (err, cbForge) { + expect(err).to.be.null; + expect(cbForge).to.be.undefined; + totalDB.unverified = 0; + done(); + }); + }, 800); + }); + + it('should be ok when get pool totals', function (done) { + var totals = transactionPool.getUsage(); + + expect(totals).to.be.an('object'); + expect(totals.unverified).to.be.equal(totalDB.unverified); + expect(totals.pending).to.be.equal(totalDB.pending); + expect(totals.ready).to.be.equal(totalDB.ready); + expect(totals.invalid).to.be.equal(totalDB.invalid); + done(); + }); }); describe('process workers', function () { @@ -272,20 +358,20 @@ describe('transactionPool', function () { done(); }); - describe('processPool - no broadcast', function () { + describe('processPool - no broadcast - addFromPeer', function () { describe('Transaction type: 0 - Transmit funds', function () { var tmpTransactionInvalidId; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -295,40 +381,39 @@ describe('transactionPool', function () { tmpTransactionInvalidId = _.cloneDeep(invalidsTransactions[0]); tmpTransactionInvalidId.id = '01234567890123456789'; - transactionPool.add(tmpTransactionInvalidId, false, function (err, cbtransaction) { + transactionPool.addFromPeer(tmpTransactionInvalidId, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; + expect(err).to.equal('Invalid transaction id'); + poolTotals.invalid += 1; done(); }); }); it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + tmpTransactionInvalidId.id); - expect(error.args[1][1]).to.equal('Invalid transaction id'); - poolTotals.invalid += 1; + expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[0].id); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3.00000001'].join(' ')); poolTotals.ready += 1; done(); }); }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[0], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); done(); }); }); it('should fail when add same transaction with invalid id to unverified', function (done) { - transactionPool.add(tmpTransactionInvalidId, false, function (err, cbtransaction) { + transactionPool.addFromPeer(tmpTransactionInvalidId, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTransactionInvalidId.id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(transactions[0]); + var deletedTransaction = transactionPool.delete(transactions[0].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -360,61 +445,57 @@ describe('transactionPool', function () { var invalidTransactionType; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with invalid transaction type', function (done) { + it('should fail when add transaction to unverified with invalid transaction type', function (done) { invalidTransactionType = _.cloneDeep(invalidsTransactions[0]); invalidTransactionType.id = '12345678901234567890'; invalidTransactionType.type = 99; - transactionPool.add(invalidTransactionType, false, function (err, cbtransaction) { - if (err) { - done(err); - } + transactionPool.addFromPeer(invalidTransactionType, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; + expect(err).to.equal(['Unknown transaction type', invalidTransactionType.type].join(' ')); + poolTotals.invalid += 1; done(); }); }); it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[1].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidTransactionType.id); - expect(error.args[1][1]).to.equal(['Unknown transaction type', invalidTransactionType.type].join(' ')); - poolTotals.invalid += 1; + expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[1].id); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 1e-8'].join(' ')); poolTotals.ready += 1; done(); }); }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); done(); }); }); it('should fail when add same transaction with invalid transaction type to unverified', function (done) { - transactionPool.add(invalidTransactionType, false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidTransactionType, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidTransactionType.id); done(); }); }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(transactions[1]); + var deletedTransaction = transactionPool.delete(transactions[1].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -446,28 +527,28 @@ describe('transactionPool', function () { var invalidSignature; it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[2], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[2][0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that already is a delegate', function (done) { - transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with same username', function (done) { - transactionPool.add(invalidsTransactions[2][2], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -476,7 +557,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -484,14 +565,14 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[2][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[2][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][1].id); - expect(error.args[1][1]).to.equal('Account is already a delegate'); - expect(error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][2].id); - expect(error.args[2][1]).to.equal('Username already exists'); - expect(error.args[3][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); - expect(error.args[3][1]).to.equal('Failed to verify signature'); + expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[2][0].id); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[2][0].senderId, 'balance: 0'].join(' ')); + expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][1].id); + expect(logger.error.args[1][1]).to.equal('Account is already a delegate'); + expect(logger.error.args[2][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][2].id); + expect(logger.error.args[2][1]).to.equal('Username already exists'); + expect(logger.error.args[3][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); + expect(logger.error.args[3][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 3; poolTotals.ready += 1; done(); @@ -499,35 +580,35 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[2], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with registered delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); it('should fail when add same transaction with same username to unverified', function (done) { - transactionPool.add(invalidsTransactions[2][2], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][2].id); done(); }); }); it('should fail when add same transaction with invalid signature to unverified', function (done) { - transactionPool.add(invalidSignature, false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidSignature.id); done(); }); @@ -565,21 +646,21 @@ describe('transactionPool', function () { describe('Transaction type: 3 - Submit votes', function () { it('should be ok when add normal transaction to unverified', function (done) { - transactionPool.add(transactions[3], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[3], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[3][0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[3][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified that votes a non delegate', function (done) { - transactionPool.add(invalidsTransactions[3][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -587,10 +668,10 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[3][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[3][1].id); - expect(error.args[1][1]).to.equal('Delegate not found'); + expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[3][0].id); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0'].join(' ')); + expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[3][1].id); + expect(logger.error.args[1][1]).to.equal('Delegate not found'); poolTotals.invalid += 1; poolTotals.ready += 1; done(); @@ -598,14 +679,14 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(transactions[3], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[3], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); done(); }); }); it('should fail when add same transaction that votes a non delegate to unverified', function (done) { - transactionPool.add(invalidsTransactions[3][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[3][1].id); done(); }); @@ -647,14 +728,14 @@ describe('transactionPool', function () { it('should be ok when add normal transaction to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not register signer in database', function (done) { - transactionPool.add(transactions[4][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -663,21 +744,21 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with not enough LSK', function (done) { - transactionPool.add(invalidsTransactions[4][0], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[4][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); it('should be ok when add transaction to unverified with invalid signeer', function (done) { - transactionPool.add(invalidsTransactions[4][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -685,10 +766,10 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[4][0].id); - expect(error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0'].join(' ')); - expect(error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[4][1].id); - expect(error.args[1][1]).to.equal('Failed to verify multisignature'); + expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[4][0].id); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0'].join(' ')); + expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[4][1].id); + expect(logger.error.args[1][1]).to.equal('Failed to verify multisignature'); poolTotals.invalid += 1; poolTotals.pending += 1; poolTotals.ready += 2; @@ -697,21 +778,21 @@ describe('transactionPool', function () { }); it('should fail when add same normal transaction to unverified', function (done) { - transactionPool.add(completedSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + completedSignatures.id); done(); }); }); it('should fail when add same transaction with unregister signer to unverified', function (done) { - transactionPool.add(transactions[4][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[4][1].id); done(); }); }); it('should fail when add same transaction without enough signatures to unverified', function (done) { - transactionPool.add(invalidsTransactions[4][1], false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[4][1].id); done(); }); @@ -780,7 +861,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args.length).to.equal(0); + expect(logger.error.args.length).to.equal(0); poolTotals.pending -= 1; poolTotals.ready += 1; done(); @@ -826,7 +907,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -835,7 +916,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -844,7 +925,7 @@ describe('transactionPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -852,8 +933,8 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); - expect(error.args[0][1]).to.equal('Failed to verify signature'); + expect(logger.error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); + expect(logger.error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; poolTotals.ready += 1; poolTotals.pending += 1; @@ -864,7 +945,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - transactionPool.add(normalTransaction, false, function (err, cbtransaction) { + transactionPool.addFromPeer(normalTransaction, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -912,10 +993,10 @@ describe('transactionPool', function () { it('should be ok when exprire transactions', function (done) { setTimeout(function () { transactionPool.expireTransactions(function (err, cbprPool) { - expect(info.args.length).to.equal(3); - expect(info.args[0][0]).to.equal(['Expired transaction:', normalTransaction.id, 'received at:', normalTransaction.receivedAt.toUTCString()].join(' ')); - expect(info.args[1][0]).to.equal(['Expired transaction:', notEnoughSignatures.id, 'received at:', notEnoughSignatures.receivedAt.toUTCString()].join(' ')); - expect(info.args[2][0]).to.equal(['Expired transaction:', completedSignatures.id, 'received at:', completedSignatures.receivedAt.toUTCString()].join(' ')); + expect(logger.info.args.length).to.equal(3); + expect(logger.info.args[0][0]).to.equal(['Expired transaction:', normalTransaction.id, 'received at:', normalTransaction.receivedAt.toUTCString()].join(' ')); + expect(logger.info.args[1][0]).to.equal(['Expired transaction:', notEnoughSignatures.id, 'received at:', notEnoughSignatures.receivedAt.toUTCString()].join(' ')); + expect(logger.info.args[2][0]).to.equal(['Expired transaction:', completedSignatures.id, 'received at:', completedSignatures.receivedAt.toUTCString()].join(' ')); poolTotals.pending -= 1; poolTotals.ready -= 1; poolTotals.unverified -= 1; @@ -957,7 +1038,7 @@ describe('transactionPool', function () { it('should be ok when add transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); - transactionPool.add(invalidSignature, false, function (err, cbtransaction) { + transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -966,7 +1047,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); - transactionPool.add(completedSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -975,7 +1056,7 @@ describe('transactionPool', function () { it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); - transactionPool.add(notEnoughSignatures, false, function (err, cbtransaction) { + transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -983,8 +1064,8 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); - expect(error.args[0][1]).to.equal('Failed to verify signature'); + expect(logger.error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); + expect(logger.error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; poolTotals.ready += 1; poolTotals.pending += 1; @@ -995,7 +1076,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); - transactionPool.add(normalTransaction, false, function (err, cbtransaction) { + transactionPool.addFromPeer(normalTransaction, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -1005,7 +1086,7 @@ describe('transactionPool', function () { it('should be ok when add normal transaction type 3 to unverified', function (done) { var normalTransactionT3 = _.cloneDeep(transactions[3]); normalTransactionT3.requesterPublicKey = '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'; - transactionPool.add(normalTransactionT3, false, function (err, cbtransaction) { + transactionPool.addFromPeer(normalTransactionT3, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; done(); @@ -1156,7 +1237,7 @@ describe('transactionPool', function () { transactions.push(e); } }); - transactionPool.add(transactions, false, function (err, cbtransaction) { + transactionPool.addFromPeer(transactions, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; expect(err).to.equal('Transaction pool is full'); done(); @@ -1174,7 +1255,7 @@ describe('transactionPool', function () { it('should fail when add transaction and pool storage is full', function (done) { var extraTransaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret); - transactionPool.add(extraTransaction, false, function (err, cbtransaction) { + transactionPool.addFromPeer(extraTransaction, false, function (err, cbtransaction) { expect(err).to.equal('Transaction pool is full'); done(); }); From d31b8faecc8855d2c021d367c21991270df27e89 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 14 Nov 2017 11:18:24 +0100 Subject: [PATCH 53/86] Delete normalize transaction function --- logic/transactions/pool.js | 76 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 5f17e229193..63f7444ac90 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -246,27 +246,28 @@ __private.processTransaction = function (transaction, sender, requester, waterCb }; /** - * Normalizes transaction. + * Verifyes transaction. * @private - * @implements {library.logic.transaction.objectNormalize} + * @implements {library.logic.transaction.verify} * @implements {__private.addInvalid} * @param {Object} transaction * @param {Object} sender * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.normalizeTransaction = function (transaction, sender, waterCb) { - try { - transaction = library.logic.transaction.objectNormalize(transaction); - return setImmediate(waterCb, null, transaction, sender); - } catch (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err, null); - } +__private.verifyTransaction = function (transaction, sender, waterCb) { + library.logic.transaction.verify(transaction, sender, function (err) { + if (err) { + __private.addInvalid(transaction.id); + return setImmediate(waterCb, err); + } else { + return setImmediate(waterCb, null, transaction, sender); + } + }); }; /** - * Verifyes transaction. + * Verifies if transaction type is repeated into pool from same sender. * @private * @implements {library.logic.transaction.verify} * @implements {__private.addInvalid} @@ -275,15 +276,24 @@ __private.normalizeTransaction = function (transaction, sender, waterCb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.verifyTransaction = function (transaction, sender, waterCb) { - library.logic.transaction.verify(transaction, sender, function (err) { - if (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } else { +__private.verifyTransactionTypeInPool = function (transaction, sender, waterCb) { + var senderTransactions = _.filter(pool.verified.ready.transactions, {'senderPublicKey': transaction.senderPublicKey}); + + if (senderTransactions.length > 0) { + if (transaction.type === transactionTypes.SIGNATURE) { + senderTransactions.forEach(function (transactionReady) { + self.delete(transactionReady.id); + }); + } + if (transaction.type === transactionTypes.VOTE) { + + } + if (transaction.type === transactionTypes.MULTI) { return setImmediate(waterCb, null, transaction, sender); } - }); + } + + return setImmediate(waterCb, null, transaction, sender); }; /** @@ -314,7 +324,6 @@ __private.moveToVerified = function (transaction, cb) { * @implements {__private.setAccountAndGet} * @implements {__private.getAccount} * @implements {__private.processTransaction} - * @implements {__private.normalizeTransaction} * @implements {__private.verifyTransaction} * @implements {__private.moveToVerified} * @param {Transaction} transaction @@ -329,8 +338,8 @@ __private.addToVerified = function (transaction, broadcast, cb) { __private.setAccountAndGet, __private.getRequester, __private.processTransaction, - __private.normalizeTransaction, __private.verifyTransaction, + __private.verifyTransactionTypeInPool, function checkBalance (transaction, sender, waterCb) { self.checkBalance(transaction, sender, function (err, balance) { if (err) { @@ -353,7 +362,6 @@ __private.addToVerified = function (transaction, broadcast, cb) { * @implements {__private.setAccountAndGet} * @implements {__private.getAccount} * @implements {__private.processTransaction} - * @implements {__private.normalizeTransaction} * @param {Transaction} transaction * @param {boolean} broadcast * @param {function} cb - Callback function. @@ -364,8 +372,7 @@ __private.addToUnverified = function (transaction, broadcast, cb) { async.apply(__private.checkPoolAvailability, transaction), __private.setAccountAndGet, __private.getRequester, - __private.processTransaction, - __private.normalizeTransaction + __private.processTransaction ], function (err, transaction, sender) { if (!err) { if (broadcast) { @@ -517,30 +524,17 @@ __private.transactionTimeOut = function (transaction) { /** * Gets sender account, and verifies transaction. * @private - * @implements {accounts.setAccountAndGet} - * @implements {accounts.getAccount} - * @implements {logic.transaction.process} - * @implements {logic.transaction.verify} + * @implements {__private.setAccountAndGet} + * @implements {__private.verifyTransaction} * @param {transaction} transaction * @param {function} cb - Callback function * @returns {setImmediateCallback} errors | sender */ __private.processUnverifiedTransaction = function (transaction, cb) { async.waterfall([ - function setAccountAndGet (waterCb) { - modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, waterCb); - }, - function verifyTransaction (sender, waterCb) { - library.logic.transaction.verify(transaction, sender, function (err) { - if (err) { - __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, sender); - } - }); - } - ], function (err, sender) { + async.apply(__private.setAccountAndGet, transaction), + __private.verifyTransaction + ], function (err, transaction, sender) { return setImmediate(cb, err, sender); }); }; From f06f9ad2f6d3adca8dbdf07f59115edd3416265d Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 15 Nov 2017 17:34:41 +0100 Subject: [PATCH 54/86] Connect new pool with modules transactions --- modules/transactions.js | 87 ++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 50 deletions(-) diff --git a/modules/transactions.js b/modules/transactions.js index be2249c382c..36df1396404 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -8,7 +8,7 @@ var extend = require('extend'); var OrderBy = require('../helpers/orderBy.js'); var schema = require('../schema/transactions.js'); var sql = require('../sql/transactions.js'); -var TransactionPool = require('../logic/transactionPool.js'); +var TransactionPool = require('../logic/transactions/pool.js'); var transactionTypes = require('../helpers/transactionTypes.js'); var Transfer = require('../logic/transfer.js'); @@ -49,11 +49,14 @@ function Transactions (cb, scope) { self = this; __private.transactionPool = new TransactionPool( - scope.config.broadcasts.broadcastInterval, - scope.config.broadcasts.releaseLimit, + scope.config.transactions.pool.storageLimit, + scope.config.transactions.pool.processInterval, + scope.config.transactions.pool.expiryInterval, scope.logic.transaction, + scope.logic.account, scope.bus, - scope.logger + scope.logger, + scope.ed ); __private.assetTypes[transactionTypes.SEND] = library.logic.transaction.attachAssetType( @@ -344,73 +347,65 @@ __private.getPooledTransactions = function (method, req, cb) { // Public methods /** - * Check if transaction is in pool + * Check if transaction is in pool. + * @implements {transactionPool.get} * @param {string} id - * @return {function} Calls transactionPool.transactionInPool + * @return {boolean} False if transaction not in pool. */ Transactions.prototype.transactionInPool = function (id) { - return __private.transactionPool.transactionInPool(id); + var transaction = __private.transactionPool.get(id); + return transaction.status === 'Transaction not in pool' ? false : true; }; /** + * Gets transaction from pool and check if is in pending signature list. + * @implements {transactionPool.get} * @param {string} id - * @return {function} Calls transactionPool.getUnconfirmedTransaction - */ -Transactions.prototype.getUnconfirmedTransaction = function (id) { - return __private.transactionPool.getUnconfirmedTransaction(id); -}; - -/** - * @param {string} id - * @return {function} Calls transactionPool.getQueuedTransaction - */ -Transactions.prototype.getQueuedTransaction = function (id) { - return __private.transactionPool.getQueuedTransaction(id); -}; - -/** - * @param {string} id - * @return {function} Calls transactionPool.getMultisignatureTransaction + * @return {transaction|undefined} Calls transactionPool.getMultisignatureTransaction */ Transactions.prototype.getMultisignatureTransaction = function (id) { - return __private.transactionPool.getMultisignatureTransaction(id); + var transaction = __private.transactionPool.get(id); + return transaction.status === 'pending' ? transaction.transaction : undefined; }; /** - * Gets unconfirmed transactions based on limit and reverse option. - * @param {boolean} reverse + * Gets unconfirmed transactions based on limit. + * @implements {transactionPool.getReady} * @param {number} limit - * @return {function} Calls transactionPool.getUnconfirmedTransactionList + * @return {transaction[]} */ -Transactions.prototype.getUnconfirmedTransactionList = function (reverse, limit) { - return __private.transactionPool.getUnconfirmedTransactionList(reverse, limit); +Transactions.prototype.getUnconfirmedTransactionList = function (limit) { + return __private.transactionPool.getReady(limit); }; /** * Gets queued transactions based on limit and reverse option. + * @implements {transactionPool.getAll} * @param {boolean} reverse * @param {number} limit - * @return {function} Calls transactionPool.getQueuedTransactionList + * @return {transaction[]} */ Transactions.prototype.getQueuedTransactionList = function (reverse, limit) { - return __private.transactionPool.getQueuedTransactionList(reverse, limit); + return __private.transactionPool.getAll('unverified', {reverse: reverse, limit: limit}); }; /** - * Gets multisignature transactions based on limit and reverse option. + * Gets multisignature transactions based on limit. + * @implements {transactionPool.getAll} * @param {boolean} reverse * @param {number} limit * @return {function} Calls transactionPool.getQueuedTransactionList */ Transactions.prototype.getMultisignatureTransactionList = function (reverse, limit) { - return __private.transactionPool.getMultisignatureTransactionList(reverse, limit); + return __private.transactionPool.getAll('pending', {reverse: reverse, limit: limit}); }; /** - * Gets unconfirmed, multisignature and queued transactions based on limit and reverse option. + * Gets ready, pending and unverified transactions based on limit and reverse option. + * @implements {transactionPool.getMergedTransactionList} * @param {boolean} reverse * @param {number} limit - * @return {function} Calls transactionPool.getMergedTransactionList + * @return {function} ready + pending + unverified */ Transactions.prototype.getMergedTransactionList = function (reverse, limit) { return __private.transactionPool.getMergedTransactionList(reverse, limit); @@ -418,23 +413,23 @@ Transactions.prototype.getMergedTransactionList = function (reverse, limit) { /** * Removes transaction from unconfirmed, queued and multisignature. + * @implements {transactionPool.delete} * @param {string} id * @return {function} Calls transactionPool.removeUnconfirmedTransaction */ Transactions.prototype.removeUnconfirmedTransaction = function (id) { - return __private.transactionPool.removeUnconfirmedTransaction(id); + return __private.transactionPool.delete(id); }; /** - * Checks kind of unconfirmed transaction and process it, resets queue - * if limit reached. + * Adds a transaction to pool list. It will be processed later by processPool worker. + * @implements {transactionPool.addToUnverified} * @param {transaction} transaction - * @param {Object} broadcast + * @param {boolean} broadcast * @param {function} cb - Callback function. - * @return {function} Calls transactionPool.processUnconfirmedTransaction */ Transactions.prototype.processUnconfirmedTransaction = function (transaction, broadcast, cb) { - return __private.transactionPool.processUnconfirmedTransaction(transaction, broadcast, cb); + return __private.transactionPool.addToUnverified(transaction, broadcast, cb); }; /** @@ -668,10 +663,6 @@ Transactions.prototype.shared = { }); }, - getQueuedTransaction: function (req, cb) { - return __private.getPooledTransaction('getQueuedTransaction', req, cb); - }, - getQueuedTransactions: function (req, cb) { return __private.getPooledTransactions('getQueuedTransactionList', req, cb); }, @@ -684,10 +675,6 @@ Transactions.prototype.shared = { return __private.getPooledTransactions('getMultisignatureTransactionList', req, cb); }, - getUnconfirmedTransaction: function (req, cb) { - return __private.getPooledTransaction('getUnconfirmedTransaction', req, cb); - }, - getUnconfirmedTransactions: function (req, cb) { return __private.getPooledTransactions('getUnconfirmedTransactionList', req, cb); }, From 9c2d4170f8f160c24778ea8d7fb1a84e2e4bd67d Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 2 Nov 2017 17:06:17 +0100 Subject: [PATCH 55/86] Replace fillPool with processPool --- modules/delegates.js | 4 ++-- modules/transactions.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/delegates.js b/modules/delegates.js index 27ecf7bf67b..cc685d5450b 100644 --- a/modules/delegates.js +++ b/modules/delegates.js @@ -591,7 +591,7 @@ Delegates.prototype.onRoundChanged = function (data) { /** * Loads delegates. - * @implements module:transactions#Transactions~fillPool + * @implements module:transactions#Transactions~processPool */ Delegates.prototype.onBlockchainReady = function () { __private.loaded = true; @@ -607,7 +607,7 @@ Delegates.prototype.onBlockchainReady = function () { async.waterfall([ __private.forge, - modules.transactions.fillPool + modules.transactions.processPool ], function () { return setImmediate(cb); }); diff --git a/modules/transactions.js b/modules/transactions.js index 36df1396404..0f4a139558d 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -423,13 +423,13 @@ Transactions.prototype.removeUnconfirmedTransaction = function (id) { /** * Adds a transaction to pool list. It will be processed later by processPool worker. - * @implements {transactionPool.addToUnverified} + * @implements {transactionPool.add} * @param {transaction} transaction * @param {boolean} broadcast * @param {function} cb - Callback function. */ Transactions.prototype.processUnconfirmedTransaction = function (transaction, broadcast, cb) { - return __private.transactionPool.addToUnverified(transaction, broadcast, cb); + return __private.transactionPool.add(transaction, broadcast, cb); }; /** @@ -552,10 +552,10 @@ Transactions.prototype.receiveTransactions = function (transactions, broadcast, /** * Fills pool. * @param {function} cb - Callback function. - * @return {function} Calls transactionPool.fillPool + * @return {function} Calls transactionPool.processPool */ -Transactions.prototype.fillPool = function (cb) { - return __private.transactionPool.fillPool(cb); +Transactions.prototype.processPool = function (cb) { + return __private.transactionPool.processPool(cb); }; /** From 621969c5aa2b6c74df3c9b5a9f58f936996d3676 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 3 Nov 2017 10:46:15 +0100 Subject: [PATCH 56/86] Move transactionPool from private to logic component --- app.js | 5 +++++ test/node.js | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/app.js b/app.js index 8b8e1f0fa60..248ffd570b5 100644 --- a/app.js +++ b/app.js @@ -77,6 +77,7 @@ process.env.TOP = appConfig.topAccounts; var config = { db: appConfig.db, cache: appConfig.redis, + pool: appConfig.transactions.pool, cacheEnabled: appConfig.cacheEnabled, modules: { accounts: './modules/accounts.js', @@ -436,6 +437,7 @@ d.run(function () { */ logic: ['db', 'bus', 'schema', 'genesisblock', function (scope, cb) { var Transaction = require('./logic/transaction.js'); + var TransactionPool = require('./logic/transactions/pool.js'); var Block = require('./logic/block.js'); var Account = require('./logic/account.js'); var Peers = require('./logic/peers.js'); @@ -467,6 +469,9 @@ d.run(function () { transaction: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'logger', function (scope, cb) { new Transaction(scope.db, scope.ed, scope.schema, scope.genesisblock, scope.account, scope.logger, cb); }], + transactionPool: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'logger', 'transaction', function (scope, cb) { + new TransactionPool(scope.bus, scope.ed, scope.transaction, scope.account, scope.logger, config.pool, cb); + }], block: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'transaction', function (scope, cb) { new Block(scope.ed, scope.schema, scope.transaction, cb); }], diff --git a/test/node.js b/test/node.js index ca976f7bde4..198f268c66f 100644 --- a/test/node.js +++ b/test/node.js @@ -544,6 +544,7 @@ node.initApplication = function (cb, initScope) { }], logic: ['db', 'bus', 'schema', 'network', 'genesisblock', function (scope, cb) { var Transaction = require('../logic/transaction.js'); + var TransactionPool = require('../logic/transactions/pool.js'); var Block = require('../logic/block.js'); var Multisignature = require('../logic/multisignature.js'); var Account = require('../logic/account.js'); @@ -576,6 +577,9 @@ node.initApplication = function (cb, initScope) { transaction: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'logger', function (scope, cb) { new Transaction(scope.db, scope.ed, scope.schema, scope.genesisblock, scope.account, scope.logger, cb); }], + transactionPool: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'logger', 'transaction', function (scope, cb) { + new TransactionPool(scope.bus, scope.ed, scope.transaction, scope.account, scope.logger, node.config.transactions.pool, cb); + }], block: ['db', 'bus', 'ed', 'schema', 'genesisblock', 'account', 'transaction', function (scope, cb) { new Block(scope.ed, scope.schema, scope.transaction, cb); }], From 92adb51b19e36cf69b6b3b2b0f0c67752f16a0dd Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 6 Nov 2017 17:57:56 +0100 Subject: [PATCH 57/86] Call pool from library logic --- logic/transactions/pool.js | 14 ++------ modules/transactions.js | 66 ++++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 63f7444ac90..bbcbb315100 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -279,18 +279,8 @@ __private.verifyTransaction = function (transaction, sender, waterCb) { __private.verifyTransactionTypeInPool = function (transaction, sender, waterCb) { var senderTransactions = _.filter(pool.verified.ready.transactions, {'senderPublicKey': transaction.senderPublicKey}); - if (senderTransactions.length > 0) { - if (transaction.type === transactionTypes.SIGNATURE) { - senderTransactions.forEach(function (transactionReady) { - self.delete(transactionReady.id); - }); - } - if (transaction.type === transactionTypes.VOTE) { - - } - if (transaction.type === transactionTypes.MULTI) { - return setImmediate(waterCb, null, transaction, sender); - } + if (senderTransactions.length > 0 && transaction.type !== transactionTypes.SEND) { + return setImmediate(waterCb, 'Transaction type already in pool for sender', transaction, sender); } return setImmediate(waterCb, null, transaction, sender); diff --git a/modules/transactions.js b/modules/transactions.js index 0f4a139558d..7f54ed86fd0 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -42,23 +42,13 @@ function Transactions (cb, scope) { balancesSequence: scope.balancesSequence, logic: { transaction: scope.logic.transaction, + transactionPool: scope.logic.transactionPool, }, genesisblock: scope.genesisblock }; self = this; - __private.transactionPool = new TransactionPool( - scope.config.transactions.pool.storageLimit, - scope.config.transactions.pool.processInterval, - scope.config.transactions.pool.expiryInterval, - scope.logic.transaction, - scope.logic.account, - scope.bus, - scope.logger, - scope.ed - ); - __private.assetTypes[transactionTypes.SEND] = library.logic.transaction.attachAssetType( transactionTypes.SEND, new Transfer(library.logger, library.schema) ); @@ -353,7 +343,7 @@ __private.getPooledTransactions = function (method, req, cb) { * @return {boolean} False if transaction not in pool. */ Transactions.prototype.transactionInPool = function (id) { - var transaction = __private.transactionPool.get(id); + var transaction = library.logic.transactionPool.get(id); return transaction.status === 'Transaction not in pool' ? false : true; }; @@ -364,7 +354,7 @@ Transactions.prototype.transactionInPool = function (id) { * @return {transaction|undefined} Calls transactionPool.getMultisignatureTransaction */ Transactions.prototype.getMultisignatureTransaction = function (id) { - var transaction = __private.transactionPool.get(id); + var transaction = library.logic.transactionPool.get(id); return transaction.status === 'pending' ? transaction.transaction : undefined; }; @@ -375,7 +365,7 @@ Transactions.prototype.getMultisignatureTransaction = function (id) { * @return {transaction[]} */ Transactions.prototype.getUnconfirmedTransactionList = function (limit) { - return __private.transactionPool.getReady(limit); + return library.logic.transactionPool.getReady(limit); }; /** @@ -386,7 +376,7 @@ Transactions.prototype.getUnconfirmedTransactionList = function (limit) { * @return {transaction[]} */ Transactions.prototype.getQueuedTransactionList = function (reverse, limit) { - return __private.transactionPool.getAll('unverified', {reverse: reverse, limit: limit}); + return library.logic.transactionPool.getAll('unverified', {reverse: reverse, limit: limit}); }; /** @@ -397,7 +387,7 @@ Transactions.prototype.getQueuedTransactionList = function (reverse, limit) { * @return {function} Calls transactionPool.getQueuedTransactionList */ Transactions.prototype.getMultisignatureTransactionList = function (reverse, limit) { - return __private.transactionPool.getAll('pending', {reverse: reverse, limit: limit}); + return library.logic.transactionPool.getAll('pending', {reverse: reverse, limit: limit}); }; /** @@ -408,7 +398,7 @@ Transactions.prototype.getMultisignatureTransactionList = function (reverse, lim * @return {function} ready + pending + unverified */ Transactions.prototype.getMergedTransactionList = function (reverse, limit) { - return __private.transactionPool.getMergedTransactionList(reverse, limit); + return library.logic.transactionPool.getMergedTransactionList(reverse, limit); }; /** @@ -418,18 +408,40 @@ Transactions.prototype.getMergedTransactionList = function (reverse, limit) { * @return {function} Calls transactionPool.removeUnconfirmedTransaction */ Transactions.prototype.removeUnconfirmedTransaction = function (id) { - return __private.transactionPool.delete(id); + return library.logic.transactionPool.delete(id); }; /** - * Adds a transaction to pool list. It will be processed later by processPool worker. - * @implements {transactionPool.add} + * Removes transactions from pool lists if they are present and rechecks pool balance + * for sender. + * @implements {transactionPool.sanitazeTransactions} + * @param {string} id + * @return {function} Calls transactionPool.sanitazeTransactions + */ +Transactions.prototype.sanitizeTransactionPool = function (transactions) { + return library.logic.transactionPool.sanitizeTransactions(transactions); +}; + +/** + * Adds a transaction to pool list if pass all validations. + * @implements {transactionPool.addFromPublic} * @param {transaction} transaction * @param {boolean} broadcast * @param {function} cb - Callback function. */ Transactions.prototype.processUnconfirmedTransaction = function (transaction, broadcast, cb) { - return __private.transactionPool.add(transaction, broadcast, cb); + return library.logic.transactionPool.addFromPublic(transaction, broadcast, cb); +}; + +/** + * Adds a transaction to pool list. It will be processed later by processPool worker. + * @implements {transactionPool.addFromPeer} + * @param {transaction} transactions + * @param {boolean} broadcast + * @param {function} cb - Callback function. + */ +Transactions.prototype.processPeerTransactions = function (transactions, broadcast, cb) { + return library.logic.transactionPool.addFromPeer(transactions, broadcast, cb); }; /** @@ -546,7 +558,7 @@ Transactions.prototype.undoUnconfirmed = function (transaction, cb) { * @return {function} Calls transactionPool.receiveTransactions */ Transactions.prototype.receiveTransactions = function (transactions, broadcast, cb) { - return __private.transactionPool.receiveTransactions(transactions, broadcast, cb); + return library.logic.transactionPool.receiveTransactions(transactions, broadcast, cb); }; /** @@ -555,7 +567,7 @@ Transactions.prototype.receiveTransactions = function (transactions, broadcast, * @return {function} Calls transactionPool.processPool */ Transactions.prototype.processPool = function (cb) { - return __private.transactionPool.processPool(cb); + return library.logic.transactionPool.processPool(cb); }; /** @@ -579,7 +591,7 @@ Transactions.prototype.onBind = function (scope) { transport: scope.transport }; - __private.transactionPool.bind( + library.logic.transactionPool.bind( scope.accounts, scope.transactions, scope.loader @@ -654,9 +666,9 @@ Transactions.prototype.shared = { library.db.query(sql.count).then(function (transactionsCount) { return setImmediate(cb, null, { confirmed: transactionsCount[0].count, - multisignature: __private.transactionPool.multisignature.transactions.length, - unconfirmed: __private.transactionPool.unconfirmed.transactions.length, - queued: __private.transactionPool.queued.transactions.length + multisignature: library.logic.transactionPool.multisignature.transactions.length, + unconfirmed: library.logic.transactionPool.unconfirmed.transactions.length, + queued: library.logic.transactionPool.queued.transactions.length }); }, function (err) { return setImmediate(cb, 'Unable to count transactions'); From d4b038b3b0b47fe2e6427ad13c4e53be6be84804 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Mon, 6 Nov 2017 18:16:27 +0100 Subject: [PATCH 58/86] Use pool from initApplication logic --- logic/transaction.js | 1 + modules/delegates.js | 3 ++- test/unit/logic/transactions/pool.js | 32 ++++++++-------------------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/logic/transaction.js b/logic/transaction.js index b243e35ed0a..8e898f2b2aa 100644 --- a/logic/transaction.js +++ b/logic/transaction.js @@ -663,6 +663,7 @@ Transaction.prototype.apply = function (transaction, block, sender, cb) { // Check confirmed sender balance var amount = new bignum(transaction.amount.toString()).plus(transaction.fee.toString()); + // TODO: check if this is done by pool in all the scenarios var senderBalance = this.checkBalance(amount, 'balance', transaction, sender); if (senderBalance.exceeded) { diff --git a/modules/delegates.js b/modules/delegates.js index cc685d5450b..7797622da4d 100644 --- a/modules/delegates.js +++ b/modules/delegates.js @@ -415,7 +415,8 @@ __private.loadDelegates = function (cb) { Delegates.prototype.generateDelegateList = function (cb) { library.db.query(sql.delegateList).then(function (result) { __private.delegatesList = result[0].list; - return setImmediate(cb); + // TODO: wait 0.9.10 backport to 1.0.0 to get delegate list + return setImmediate(cb, null, __private.delegatesList); }).catch(function (err) { return setImmediate(cb, err); }); diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 61788ba661b..34ef8087384 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -20,8 +20,8 @@ var testAccounts = [ isDelegate: 1, address: '2737453412992791987L', publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - balance: 5300000000000000, - u_balance: 5300000000000000 + balance: 500000000000000, + u_balance: 500000000000000 }, secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' @@ -31,8 +31,8 @@ var testAccounts = [ isDelegate: 0, address: '2896019180726908125L', publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - balance: 0, - u_balance: 0 + balance: 1000, + u_balance: 1000 }, secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', },{ @@ -41,8 +41,8 @@ var testAccounts = [ isDelegate: 0, address: '15240249857307028085L', publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', - balance: 3500000000000000, - u_balance: 3500000000000000 + balance: 300000000000000, + u_balance: 300000000000000 }, secret: 'song gather until exercise explain utility walk choice garbage cross route develop', },{ @@ -51,8 +51,8 @@ var testAccounts = [ isDelegate: 0, address: '13898484363564790288L', publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', - balance: 3500000000000000, - u_balance: 3500000000000000 + balance: 300000000000000, + u_balance: 300000000000000 }, secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', } @@ -192,21 +192,7 @@ describe('transactionPool', function () { // Wait for genesisBlock transaction being applied node.initApplication(function (err, scope) { // Init transaction logic - transactionPool = new TransactionPool( - modulesLoader.scope.config.transactions.pool.storageLimit, - modulesLoader.scope.config.transactions.pool.processInterval, - modulesLoader.scope.config.transactions.pool.expiryInterval, - scope.logic.transaction, - scope.logic.account, - modulesLoader.scope.bus, - modulesLoader.scope.logger, - modulesLoader.scope.ed - ); - transactionPool.bind( - scope.modules.accounts, - null, - scope.modules.loader - ); + transactionPool = scope.logic.transactionPool; library = scope; logger = scope.logger; done(); From 3294ed6ed51b00a8e1d12cb15314de6a5bfccf6c Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 14 Nov 2017 11:16:12 +0100 Subject: [PATCH 59/86] Implement add transaction from public or peer --- modules/transactions.js | 8 ++++++-- modules/transport.js | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/modules/transactions.js b/modules/transactions.js index 7f54ed86fd0..d5d1378f7a3 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -425,12 +425,16 @@ Transactions.prototype.sanitizeTransactionPool = function (transactions) { /** * Adds a transaction to pool list if pass all validations. * @implements {transactionPool.addFromPublic} + * @param {string} caller peer or public * @param {transaction} transaction * @param {boolean} broadcast * @param {function} cb - Callback function. */ -Transactions.prototype.processUnconfirmedTransaction = function (transaction, broadcast, cb) { - return library.logic.transactionPool.addFromPublic(transaction, broadcast, cb); +Transactions.prototype.processUnconfirmedTransaction = function (caller, transaction, broadcast, cb) { + if (caller === 'public') { + return library.logic.transactionPool.addFromPublic(transaction, broadcast, cb); + } + return library.logic.transactionPool.addFromPeer(transaction, broadcast, cb); }; /** diff --git a/modules/transport.js b/modules/transport.js index a6ba75bfc2e..0e890df81de 100644 --- a/modules/transport.js +++ b/modules/transport.js @@ -250,12 +250,16 @@ __private.receiveTransaction = function (transaction, peer, extraLogMessage, cb) } library.balancesSequence.add(function (cb) { + var caller; + if (!peer) { library.logger.debug('Received transaction ' + transaction.id + ' from public client'); + caller = 'public'; } else { library.logger.debug('Received transaction ' + transaction.id + ' from peer ' + library.logic.peers.peersManager.getAddress(peer.nonce)); + caller = 'peer'; } - modules.transactions.processUnconfirmedTransaction(transaction, true, function (err) { + modules.transactions.processUnconfirmedTransaction(caller, transaction, true, function (err) { if (err) { library.logger.debug(['Transaction', id].join(' '), err.toString()); if (transaction) { library.logger.debug('Transaction', transaction); } From 66c330aef6657bf8aef96b13dae297f01a28ffe1 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 3 Nov 2017 12:54:29 +0100 Subject: [PATCH 60/86] Refactor generateBlock to call applyBlock --- modules/blocks/process.js | 66 +++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/modules/blocks/process.js b/modules/blocks/process.js index cbe2986438d..cd2f3d6a795 100644 --- a/modules/blocks/process.js +++ b/modules/blocks/process.js @@ -7,6 +7,7 @@ var Peer = require('../../logic/peer.js'); var schema = require('../../schema/blocks.js'); var slots = require('../../helpers/slots.js'); var sql = require('../../sql/blocks.js'); +var bson = require('../../helpers/bson.js'); var modules, library, self, __private = {}; @@ -469,45 +470,34 @@ Process.prototype.loadBlocksFromPeer = function (peer, cb) { */ Process.prototype.generateBlock = function (keypair, timestamp, cb) { // Get transactions that will be included in block - var transactions = modules.transactions.getUnconfirmedTransactionList(false, constants.maxTxsPerBlock); - var ready = []; - - async.eachSeries(transactions, function (transaction, cb) { - modules.accounts.getAccount({ publicKey: transaction.senderPublicKey }, function (err, sender) { - if (err || !sender) { - return setImmediate(cb, 'Sender not found'); - } - - // Check transaction depends on type - if (library.logic.transaction.ready(transaction, sender)) { - // Verify transaction - library.logic.transaction.verify(transaction, sender, function (err) { - ready.push(transaction); - return setImmediate(cb); - }); - } else { - return setImmediate(cb); - } + var ready = modules.transactions.getUnconfirmedTransactionList(false, constants.maxTxsPerBlock); + var lastBlock = modules.blocks.lastBlock.get(); + var block; + + try { + // Create a block + block = library.logic.block.create({ + keypair: keypair, + timestamp: timestamp, + previousBlock: lastBlock, + transactions: ready }); - }, function () { - var block; - - try { - // Create a block - block = library.logic.block.create({ - keypair: keypair, - timestamp: timestamp, - previousBlock: modules.blocks.lastBlock.get(), - transactions: ready - }); - } catch (e) { - library.logger.error(e.stack); - return setImmediate(cb, e); - } - - // Start block processing - broadcast: true, saveBlock: true - modules.blocks.verify.processBlock(block, true, cb, true); - }); + } catch (e) { + library.logger.error(e.stack); + return setImmediate(cb, e); + } + // Set block missed values + block.id = library.logic.block.getId(block); + block.height = lastBlock.height + 1; + + // Delete default properties + var blockReduced = modules.blocks.verify.deleteBlockProperties(block); + var serializedBlockReduced = bson.serialize(blockReduced); + // Broadcast block - broadcast: true + modules.blocks.chain.broadcastReducedBlock(serializedBlockReduced, block.id, true); + + // Apply block - saveBlock: true + modules.blocks.chain.applyBlock(block, true, cb); }; /** From bc39d70dfda163a8986046f2f9df9214f0a314bf Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 3 Nov 2017 15:13:11 +0100 Subject: [PATCH 61/86] Refactor applyBlock to use new transaction pool --- modules/blocks/chain.js | 95 +++++------------------------------------ 1 file changed, 10 insertions(+), 85 deletions(-) diff --git a/modules/blocks/chain.js b/modules/blocks/chain.js index 328f9b4d831..c9c90da5e0a 100644 --- a/modules/blocks/chain.js +++ b/modules/blocks/chain.js @@ -333,83 +333,14 @@ Chain.prototype.applyBlock = function (block, saveBlock, cb) { // Prevent shutdown during database writes. modules.blocks.isActive.set(true); - // Transactions to rewind in case of error. - var appliedTransactions = {}; - - // List of unconfirmed transactions ids. - var unconfirmedTransactionIds; - async.series({ - // Rewind any unconfirmed transactions before applying block. - // TODO: It should be possible to remove this call if we can guarantee that only this function is processing transactions atomically. Then speed should be improved further. - // TODO: Other possibility, when we rebuild from block chain this action should be moved out of the rebuild function. - undoUnconfirmedList: function (seriesCb) { - modules.transactions.undoUnconfirmedList(function (err, ids) { - if (err) { - // Fatal error, memory tables will be inconsistent - library.logger.error('Failed to undo unconfirmed list', err); + // TODO: new series: after validate block, validate each transaction and insert into database, + // sanitize transactionPool: delete transaction.id and if sender or receipt are in ready pool + // list, checkbalance again - return process.exit(0); - } else { - unconfirmedTransactionIds = ids; - return setImmediate(seriesCb); - } - }); - }, - // Apply transactions to unconfirmed mem_accounts fields. - applyUnconfirmed: function (seriesCb) { - async.eachSeries(block.transactions, function (transaction, eachSeriesCb) { - // DATABASE write - modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, function (err, sender) { - // DATABASE: write - modules.transactions.applyUnconfirmed(transaction, sender, function (err) { - if (err) { - err = ['Failed to apply transaction:', transaction.id, '-', err].join(' '); - library.logger.error(err); - library.logger.error('Transaction', transaction); - return setImmediate(eachSeriesCb, err); - } - - appliedTransactions[transaction.id] = transaction; - - // Remove the transaction from the node queue, if it was present. - var index = unconfirmedTransactionIds.indexOf(transaction.id); - if (index >= 0) { - unconfirmedTransactionIds.splice(index, 1); - } - - return setImmediate(eachSeriesCb); - }); - }); - }, function (err) { - if (err) { - // Rewind any already applied unconfirmed transactions. - // Leaves the database state as per the previous block. - async.eachSeries(block.transactions, function (transaction, eachSeriesCb) { - modules.accounts.getAccount({publicKey: transaction.senderPublicKey}, function (err, sender) { - if (err) { - return setImmediate(eachSeriesCb, err); - } - // The transaction has been applied? - if (appliedTransactions[transaction.id]) { - // DATABASE: write - library.logic.transaction.undoUnconfirmed(transaction, sender, eachSeriesCb); - } else { - return setImmediate(eachSeriesCb); - } - }); - }, function (err) { - return setImmediate(seriesCb, err); - }); - } else { - return setImmediate(seriesCb); - } - }); - }, - // Block and transactions are ok. - // Apply transactions to confirmed mem_accounts fields. - applyConfirmed: function (seriesCb) { + applyTransactions: function (seriesCb) { async.eachSeries(block.transactions, function (transaction, eachSeriesCb) { + // TODO: improve transaction to avoid call getAccount to get sender address modules.accounts.getAccount({publicKey: transaction.senderPublicKey}, function (err, sender) { if (err) { // Fatal error, memory tables will be inconsistent @@ -429,8 +360,6 @@ Chain.prototype.applyBlock = function (block, saveBlock, cb) { return process.exit(0); } - // Transaction applied, removed from the unconfirmed list. - modules.transactions.removeUnconfirmedTransaction(transaction.id); return setImmediate(eachSeriesCb); }); }); @@ -461,21 +390,17 @@ Chain.prototype.applyBlock = function (block, saveBlock, cb) { return seriesCb(); } }, - // Push back unconfirmed transactions list (minus the one that were on the block if applied correctly). - // TODO: See undoUnconfirmedList discussion above. - applyUnconfirmedIds: function (seriesCb) { - // DATABASE write - modules.transactions.applyUnconfirmedIds(unconfirmedTransactionIds, function (err) { - return setImmediate(seriesCb, err); - }); - }, + sanitizeTransactionPool: function (seriesCb) { + modules.transactions.sanitizeTransactionPool(block.transactions); + return seriesCb(); + } }, function (err) { // Allow shutdown, database writes are finished. modules.blocks.isActive.set(false); // Nullify large objects. // Prevents memory leak during synchronisation. - appliedTransactions = unconfirmedTransactionIds = block = null; + block = null; // Finish here if snapshotting. // FIXME: Not the best place to do that From b59d4612a79299be4d794db47f3f645a21e52e25 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 16 Nov 2017 00:26:36 +0100 Subject: [PATCH 62/86] Adjust test --- modules/transactions.js | 6 +- test/unit/logic/transactions/pool.js | 87 +++++++++++++++++----------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/modules/transactions.js b/modules/transactions.js index d5d1378f7a3..f0001583347 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -464,7 +464,8 @@ Transactions.prototype.applyUnconfirmedList = function (cb) { * @return {function} Calls transactionPool.applyUnconfirmedIds */ Transactions.prototype.applyUnconfirmedIds = function (ids, cb) { - return __private.transactionPool.applyUnconfirmedIds(ids, cb); + // TODO: delete this function + cb(); }; /** @@ -473,7 +474,8 @@ Transactions.prototype.applyUnconfirmedIds = function (ids, cb) { * @return {function} Calls transactionPool.undoUnconfirmedList */ Transactions.prototype.undoUnconfirmedList = function (cb) { - return __private.transactionPool.undoUnconfirmedList(cb); + // TODO: delete this function + cb(); }; /** diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 34ef8087384..35297c3084a 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -17,42 +17,34 @@ var testAccounts = [ { account: { username: 'tpool_test_1', - isDelegate: 1, address: '2737453412992791987L', publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - balance: 500000000000000, - u_balance: 500000000000000 + balance: 500000000000000 }, secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' },{ account: { username: 'tpool_test_2', - isDelegate: 0, address: '2896019180726908125L', publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - balance: 1000, - u_balance: 1000 + balance: 1000 }, secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', },{ account: { username: 'tpool_test_3', - isDelegate: 0, address: '15240249857307028085L', publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', - balance: 300000000000000, - u_balance: 300000000000000 + balance: 300000000000000 }, secret: 'song gather until exercise explain utility walk choice garbage cross route develop', },{ account: { username: 'tpool_test_4', - isDelegate: 0, address: '13898484363564790288L', publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', - balance: 300000000000000, - u_balance: 300000000000000 + balance: 300000000000000 }, secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', } @@ -86,17 +78,17 @@ var transactions = [ var invalidsTransactions = [ /* Type: 0 - Transmit funds account without enough credit.*/ - node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000, testAccounts[1].secret), + node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000000, testAccounts[1].secret), /* Type: 1 - Register a second signature account without enough credit.*/ node.lisk.signature.createSignature(testAccounts[1].secret, testAccounts[0].secret2), /* Type: 2.*/ [ /* - Register a delegate account without enough credit.*/ - node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'tpool_new_delegate'), + node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'no_credit'), /* - Register a delegate that already is delegate*/ node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), /* - Register a delegate account with existing username*/ - node.lisk.delegate.createDelegate(testAccounts[1].secret, testAccounts[1].account.username) + node.lisk.delegate.createDelegate(testAccounts[1].secret, 'genesis_101') ], /* Type: 3.*/ [ @@ -191,7 +183,6 @@ describe('transactionPool', function () { modulesLoader.scope.config.transactions.pool.expiryInterval = 80000000; // Wait for genesisBlock transaction being applied node.initApplication(function (err, scope) { - // Init transaction logic transactionPool = scope.logic.transactionPool; library = scope; logger = scope.logger; @@ -295,6 +286,15 @@ describe('transactionPool', function () { }); }); + it('should be ok when add delegate transaction to unverified', function (done) { + transaction = node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; + done(); + }); + }); + it('should be ok when get pool totals to initialize local counter', function (done) { var totals = transactionPool.getUsage(); @@ -328,6 +328,26 @@ describe('transactionPool', function () { expect(totals.invalid).to.be.equal(totalDB.invalid); done(); }); + + it('should be ok when add delegate transaction to unverified', function (done) { + transaction = node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username); + + transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { + expect(cbtransaction).to.be.undefined; + done(); + }); + }); + + it('should be ok when process transactions and create blocks', function (done) { + setTimeout(function () { + forge(function (err, cbForge) { + expect(err).to.be.null; + expect(cbForge).to.be.undefined; + totalDB.unverified = 0; + done(); + }); + }, 800); + }); }); describe('process workers', function () { @@ -378,7 +398,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[0].id); - expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3.00000001'].join(' ')); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3.00001'].join(' ')); poolTotals.ready += 1; done(); }); @@ -410,8 +430,8 @@ describe('transactionPool', function () { it('should be ok when reset invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); - expect(invalidTransactions).to.equal(1); - poolTotals.invalid -= 1; + expect(invalidTransactions).to.equal(poolTotals.invalid); + poolTotals.invalid -= invalidTransactions; done(); }); @@ -460,7 +480,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[1].id); - expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 1e-8'].join(' ')); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0.00001'].join(' ')); poolTotals.ready += 1; done(); }); @@ -601,7 +621,7 @@ describe('transactionPool', function () { }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(transactions[2]); + var deletedTransaction = transactionPool.delete(transactions[2].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -655,7 +675,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[3][0].id); - expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0'].join(' ')); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0.00001'].join(' ')); expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[3][1].id); expect(logger.error.args[1][1]).to.equal('Delegate not found'); poolTotals.invalid += 1; @@ -679,7 +699,7 @@ describe('transactionPool', function () { }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(transactions[3]); + var deletedTransaction = transactionPool.delete(transactions[3].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -753,7 +773,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[4][0].id); - expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0'].join(' ')); + expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0.00001'].join(' ')); expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[4][1].id); expect(logger.error.args[1][1]).to.equal('Failed to verify multisignature'); poolTotals.invalid += 1; @@ -785,7 +805,7 @@ describe('transactionPool', function () { }); it('should be ok when delete normal transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(completedSignatures); + var deletedTransaction = transactionPool.delete(completedSignatures.id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -794,7 +814,7 @@ describe('transactionPool', function () { }); it('should be ok when delete normal transaction without enough signatures to unverified', function (done) { - var deletedTransaction = transactionPool.delete(transactions[4][1]); + var deletedTransaction = transactionPool.delete(transactions[4][1].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -862,7 +882,7 @@ describe('transactionPool', function () { }); it('should be ok when delete transaction from ready', function (done) { - var deletedTransaction = transactionPool.delete(transactions[4][2]); + var deletedTransaction = transactionPool.delete(transactions[4][2].id); expect(deletedTransaction.length).to.equal(1); expect(deletedTransaction[0]).to.equal('ready'); @@ -1055,6 +1075,7 @@ describe('transactionPool', function () { poolTotals.invalid += 1; poolTotals.ready += 1; poolTotals.pending += 1; + poolTotals.unverified = 0; done(); }); }); @@ -1122,7 +1143,7 @@ describe('transactionPool', function () { it('should be ok when check pool list unverified', function (done) { var transactions = transactionPool.getAll('unverified', {limit: null}); - expect(Object.keys(transactions).length).to.equal(2); + expect(Object.keys(transactions).length).to.equal(poolTotals.unverified); done(); }); @@ -1251,7 +1272,7 @@ describe('transactionPool', function () { describe('method delete', function () { it('should be ok when delete a transaction from unverified', function (done) { - var deleteTransaction = transactionPool.delete(invalidsTransactions[0]); + var deleteTransaction = transactionPool.delete(invalidsTransactions[0].id); expect(deleteTransaction).to.be.an('array').that.is.not.empty; expect(deleteTransaction.length).to.equal(1); @@ -1269,7 +1290,7 @@ describe('transactionPool', function () { }); it('should fail when delete transaction that is not in pool', function (done) { - var deleteTransaction = transactionPool.delete(transactions[0]); + var deleteTransaction = transactionPool.delete(transactions[0].id); expect(deleteTransaction).to.be.an('array').that.is.empty; done(); @@ -1337,7 +1358,7 @@ describe('transactionPool', function () { }); it('should be ok when delete transaction from ready', function (done) { - var deleteTransaction = transactionPool.delete(transactions[0]); + var deleteTransaction = transactionPool.delete(transactions[0].id); expect(deleteTransaction).to.be.an('array').that.is.not.empty; expect(deleteTransaction.length).to.equal(1); @@ -1386,14 +1407,14 @@ describe('transactionPool', function () { it('should be ok when checked account balance with enough LSK for transaction', function (done) { transactionPool.checkBalance(transactions[0], {address: transactions[0].senderId}, function (err, cbBalance) { - expect(cbBalance).to.equal('balance: 52999994'); + expect(cbBalance).to.equal('balance: 4999969'); done(); }); }); it('should fail when checked account balance with not enough LSK for transaction', function (done) { transactionPool.checkBalance(invalidsTransactions[0], { address: invalidsTransactions[0].senderId }, function (err, cbBalance) { - expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0'); + expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0.00001'); done(); }); }); From bce1582a002ff914ac4c18fb1bdd7d69814d91e1 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 16 Nov 2017 15:43:31 +0100 Subject: [PATCH 63/86] Fix local counters for getters --- logic/transactions/pool.js | 4 +- test/unit/logic/transactions/pool.js | 377 +++++++++++++-------------- 2 files changed, 188 insertions(+), 193 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index bbcbb315100..a378c5fee10 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -386,8 +386,10 @@ __private.addToUnverified = function (transaction, broadcast, cb) { * @return {setImmediateCallback} error | cb */ __private.addToPoolList = function (transaction, poolList, cb) { + if (poolList.transactions[transaction.id] === undefined) { + poolList.count++; + } poolList.transactions[transaction.id] = transaction; - poolList.count++; return setImmediate(cb); }; diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 35297c3084a..9e1948bd51f 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -13,196 +13,159 @@ var bson = require('../../../../helpers/bson.js'); var constants = require('../../../../helpers/constants.js'); var TransactionPool = require('../../../../logic/transactions/pool.js'); -var testAccounts = [ - { - account: { - username: 'tpool_test_1', - address: '2737453412992791987L', - publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', - balance: 500000000000000 - }, - secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', - secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' - },{ - account: { - username: 'tpool_test_2', - address: '2896019180726908125L', - publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', - balance: 1000 - }, - secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', - },{ - account: { - username: 'tpool_test_3', - address: '15240249857307028085L', - publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', - balance: 300000000000000 - }, - secret: 'song gather until exercise explain utility walk choice garbage cross route develop', - },{ - account: { - username: 'tpool_test_4', - address: '13898484363564790288L', - publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', - balance: 300000000000000 - }, - secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', - } -]; - -var transactions = [ - /* Type: 0 - Transmit funds.*/ - node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), - /* Type: 1 - Register a second signature.*/ - node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), - /* Type: 2 - Register a delegate.*/ - node.lisk.delegate.createDelegate(testAccounts[3].secret, 'tpool_new_delegate'), - /* Type: 3 - Submit votes.*/ - node.lisk.vote.createVote(testAccounts[0].secret, - ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), - /* Type: 4 - Multisignature registration.*/ - [ - /* - Create normal multisignature, all accounts in database */ - createMultisignatureSigned (testAccounts[0].secret, null, - ['+' + testAccounts[1].account.publicKey, '+' + testAccounts[2].account.publicKey], - [testAccounts[1].secret, testAccounts[2].secret], 1, 2), - /* - Create multisignature signed with signer account not register in database.*/ - createMultisignatureSigned (testAccounts[2].secret, null, - ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], - ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1), - /* - Create multisignature signed without enough signatures.*/ - createMultisignatureSigned (testAccounts[3].secret, null, - ['+' + testAccounts[2].account.publicKey,'+' + testAccounts[1].account.publicKey], [testAccounts[2].secret], 1, 2) - ] -]; - -var invalidsTransactions = [ - /* Type: 0 - Transmit funds account without enough credit.*/ - node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000000, testAccounts[1].secret), - /* Type: 1 - Register a second signature account without enough credit.*/ - node.lisk.signature.createSignature(testAccounts[1].secret, testAccounts[0].secret2), - /* Type: 2.*/ - [ - /* - Register a delegate account without enough credit.*/ - node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'no_credit'), - /* - Register a delegate that already is delegate*/ - node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), - /* - Register a delegate account with existing username*/ - node.lisk.delegate.createDelegate(testAccounts[1].secret, 'genesis_101') - ], - /* Type: 3.*/ - [ - /* - Submit votes from an account without enough credit.*/ - node.lisk.vote.createVote(testAccounts[1].secret, - ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), - /* - Submit votes to an account that is not a delegate.*/ - node.lisk.vote.createVote(testAccounts[2].secret, - ['+181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c']) - ], - /* Type: 4.*/ - [ - /* - Create multisignature signed from an account without enough credit.*/ - createMultisignatureSigned (testAccounts[1].secret, null, - ['+' + testAccounts[3].account.publicKey], [testAccounts[3].secret], 1, 1), - /* - Create multisignature signed with invalid signature.*/ - createMultisignatureSigned (testAccounts[3].secret, null, - ['+' + testAccounts[2].account.publicKey], [testAccounts[1].secret], 1, 1) - ] -]; - -var hackedTransactions = [ - /* Invalid signature */ - { - 'type': 2, - 'amount': 0, - 'fee': 2500000000, - 'recipientId': null, - 'senderPublicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9', - 'timestamp': 43775831, - 'asset': { - 'delegate': { - 'username': 'txp_new_delegate', - 'publicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9' - } - }, - 'signature': '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a', - 'id': '16349767733713562311' - } -]; - -// Set spies for logger -var logger; - -function resetSpiesState () { - // Reset state of spies - logger.debug.reset(); - logger.info.reset(); - logger.warn.reset(); - logger.error.reset(); -} - -function restoreSpiesState () { - // Restore state of spies - logger.debug.restore(); - logger.info.restore(); - logger.warn.restore(); - logger.error.restore(); -} - -function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { - var multisignatureTransaction = node.lisk.multisignature.createMultisignature(creatorSecret, creatorSecondSecret, keysgroup, min, lifetime); - var signatures = []; - signeersSecrets.forEach(function (secret) { - var sign = node.lisk.multisignature.signTransaction(multisignatureTransaction, secret); - signatures.push(sign); - }); - multisignatureTransaction.signatures = signatures; - return multisignatureTransaction; -} - describe('transactionPool', function () { + var testAccounts = [ + { + account: { + username: 'tpool_test_1', + address: '2737453412992791987L', + publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5', + balance: 500000000000000 + }, + secret: 'message crash glance horror pear opera hedgehog monitor connect vague chuckle advice', + secret2: 'monitor connect vague chuckle advice message crash glance horror pear opera hedgehog' + },{ + account: { + username: 'tpool_test_2', + address: '2896019180726908125L', + publicKey: '684a0259a769a9bdf8b82c5fe3054182ba3e936cf027bb63be231cd25d942adb', + balance: 1000 + }, + secret: 'joy ethics cruise churn ozone asset quote renew dutch erosion seed pioneer', + },{ + account: { + username: 'tpool_test_3', + address: '15240249857307028085L', + publicKey: '181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c', + balance: 300000000000000 + }, + secret: 'song gather until exercise explain utility walk choice garbage cross route develop', + },{ + account: { + username: 'tpool_test_4', + address: '13898484363564790288L', + publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8', + balance: 300000000000000 + }, + secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', + } + ]; + + var transactions = [ + /* Type: 0 - Transmit funds.*/ + node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), + /* Type: 1 - Register a second signature.*/ + node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), + /* Type: 2 - Register a delegate.*/ + node.lisk.delegate.createDelegate(testAccounts[3].secret, 'tpool_new_delegate'), + /* Type: 3 - Submit votes.*/ + node.lisk.vote.createVote(testAccounts[0].secret, + ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), + /* Type: 4 - Multisignature registration.*/ + [ + /* - Create normal multisignature, all accounts in database */ + createMultisignatureSigned (testAccounts[0].secret, null, + ['+' + testAccounts[1].account.publicKey, '+' + testAccounts[2].account.publicKey], + [testAccounts[1].secret, testAccounts[2].secret], 1, 2), + /* - Create multisignature signed with signer account not register in database.*/ + createMultisignatureSigned (testAccounts[2].secret, null, + ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], + ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1), + /* - Create multisignature signed without enough signatures.*/ + createMultisignatureSigned (testAccounts[3].secret, null, + ['+' + testAccounts[2].account.publicKey,'+' + testAccounts[1].account.publicKey], [testAccounts[2].secret], 1, 2) + ] + ]; + + var invalidsTransactions = [ + /* Type: 0 - Transmit funds account without enough credit.*/ + node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000000, testAccounts[1].secret), + /* Type: 1 - Register a second signature account without enough credit.*/ + node.lisk.signature.createSignature(testAccounts[1].secret, testAccounts[0].secret2), + /* Type: 2.*/ + [ + /* - Register a delegate account without enough credit.*/ + node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'no_credit'), + /* - Register a delegate that already is delegate*/ + node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), + /* - Register a delegate account with existing username*/ + node.lisk.delegate.createDelegate(testAccounts[1].secret, 'genesis_101') + ], + /* Type: 3.*/ + [ + /* - Submit votes from an account without enough credit.*/ + node.lisk.vote.createVote(testAccounts[1].secret, + ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), + /* - Submit votes to an account that is not a delegate.*/ + node.lisk.vote.createVote(testAccounts[2].secret, + ['+181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c']) + ], + /* Type: 4.*/ + [ + /* - Create multisignature signed from an account without enough credit.*/ + createMultisignatureSigned (testAccounts[1].secret, null, + ['+' + testAccounts[3].account.publicKey], [testAccounts[3].secret], 1, 1), + /* - Create multisignature signed with invalid signature.*/ + createMultisignatureSigned (testAccounts[3].secret, null, + ['+' + testAccounts[2].account.publicKey], [testAccounts[1].secret], 1, 1) + ] + ]; + + var hackedTransactions = [ + /* Invalid signature */ + { + 'type': 2, + 'amount': 0, + 'fee': 2500000000, + 'recipientId': null, + 'senderPublicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9', + 'timestamp': 43775831, + 'asset': { + 'delegate': { + 'username': 'txp_new_delegate', + 'publicKey': '911441a4984f1ed369f36bb044758d0b3e158581418832a5dd4a67f3d03387e9' + } + }, + 'signature': '6db720cd875035de6d6e91cd6f48303c1f7baab3f85074e03029af857e71e8af96cf7be33fd2b7bf650c4bf01383dbccfaaba23a4020974fcb9d1912b84a4f0a', + 'id': '16349767733713562311' + } + ]; + + // Set spies for logger + var logger; var library; var transactionPool; var poolTotals; var poolStorageTransactionsLimit; var dbSandbox; - - before(function (done) { - dbSandbox = new DBSandbox(node.config.db, 'lisk_test_logic_transactionPool'); - dbSandbox.create(function (err, __db) { - if (err) { - return done(err); - } - - constants.unconfirmedTransactionTimeOut = 1; - constants.signatureTransactionTimeOutMultiplier = 1; - constants.secondsPerHour = 1; - poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; - modulesLoader.scope.config.transactions.pool.processInterval = 60000000; - modulesLoader.scope.config.transactions.pool.expiryInterval = 80000000; - // Wait for genesisBlock transaction being applied - node.initApplication(function (err, scope) { - transactionPool = scope.logic.transactionPool; - library = scope; - logger = scope.logger; - done(); - }, {db: __db}); + + function resetSpiesState () { + // Reset state of spies + logger.debug.reset(); + logger.info.reset(); + logger.warn.reset(); + logger.error.reset(); + } + + function restoreSpiesState () { + // Restore state of spies + logger.debug.restore(); + logger.info.restore(); + logger.warn.restore(); + logger.error.restore(); + } + + function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { + var multisignatureTransaction = node.lisk.multisignature.createMultisignature(creatorSecret, creatorSecondSecret, keysgroup, min, lifetime); + var signatures = []; + signeersSecrets.forEach(function (secret) { + var sign = node.lisk.multisignature.signTransaction(multisignatureTransaction, secret); + signatures.push(sign); }); - }); - - beforeEach(function () { - resetSpiesState(); - }); - - after(function () { - restoreSpiesState(); - }); - - after(function (done) { - dbSandbox.destroy(); - node.appCleanup(done); - }); + multisignatureTransaction.signatures = signatures; + return multisignatureTransaction; + } function forge (cb) { function getNextForger (offset, cb) { @@ -246,6 +209,39 @@ describe('transactionPool', function () { }); } + before(function (done) { + dbSandbox = new DBSandbox(node.config.db, 'lisk_test_logic_transactionPool'); + dbSandbox.create(function (err, __db) { + if (err) { + return done(err); + } + + constants.unconfirmedTransactionTimeOut = 1; + constants.signatureTransactionTimeOutMultiplier = 1; + constants.secondsPerHour = 1; + poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; + modulesLoader.scope.config.transactions.pool.processInterval = 60000000; + modulesLoader.scope.config.transactions.pool.expiryInterval = 80000000; + // Wait for genesisBlock transaction being applied + node.initApplication(function (err, scope) { + transactionPool = scope.logic.transactionPool; + library = scope; + logger = scope.logger; + done(); + }, {db: __db}); + }); + }); + + beforeEach(function () { + resetSpiesState(); + }); + + after(function (done) { + restoreSpiesState(); + dbSandbox.destroy(); + node.appCleanup(done); + }); + describe('setup database', function () { var transaction; var totalDB; @@ -367,6 +363,7 @@ describe('transactionPool', function () { describe('processPool - no broadcast - addFromPeer', function () { describe('Transaction type: 0 - Transmit funds', function () { + var tmpTransactionInvalidId; it('should be ok when add normal transaction to unverified', function (done) { @@ -1075,7 +1072,6 @@ describe('transactionPool', function () { poolTotals.invalid += 1; poolTotals.ready += 1; poolTotals.pending += 1; - poolTotals.unverified = 0; done(); }); }); @@ -1090,9 +1086,8 @@ describe('transactionPool', function () { }); }); - it('should be ok when add normal transaction type 3 to unverified', function (done) { + it('should be ok when add valid transaction type 3 to unverified', function (done) { var normalTransactionT3 = _.cloneDeep(transactions[3]); - normalTransactionT3.requesterPublicKey = '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'; transactionPool.addFromPeer(normalTransactionT3, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.unverified += 1; @@ -1171,7 +1166,7 @@ describe('transactionPool', function () { it('should be ok when check pool list ready', function (done) { var transactions = transactionPool.getAll('ready', {limit: null}); - expect(Object.keys(transactions).length).to.equal(1); + expect(Object.keys(transactions).length).to.equal(poolTotals.ready); done(); }); @@ -1219,8 +1214,9 @@ describe('transactionPool', function () { done(); }); - it('should be ok when requester publicKey is valid', function (done) { - var transactions = transactionPool.getAll('recipient_pk', {publicKey: '849b37aaeb6038aebbe7e7341735d7a9d207da1851b701d87db5426651ed3fe8'}); + // TODO: turn on this test after move to new db schema + it.skip('should be ok when recipient publicKey is valid', function (done) { + var transactions = transactionPool.getAll('recipient_pk', {publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5'}); expect(transactions.unverified.length).to.equal(1); expect(transactions.pending.length).to.equal(0); @@ -1313,7 +1309,7 @@ describe('transactionPool', function () { it('should be ok when add transactions to ready', function (done) { transactionPool.addReady(allTransactions, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; - poolTotals.ready += allTransactions.length -1; + poolTotals.ready = allTransactions.length; done(); }); }); @@ -1351,9 +1347,6 @@ describe('transactionPool', function () { expect(readyTransactions.length).to.equal(2); expect(readyTransactions[0].receivedAt).to.not.equal(readyTransactions[1].receivedAt); - expect(readyTransactions[1].receivedAt).to.equal(readyTransactions[2].receivedAt); - expect(readyTransactions[2].receivedAt).to.equal(readyTransactions[3].receivedAt); - expect(readyTransactions[3].receivedAt).to.equal(readyTransactions[4].receivedAt); done(); }); From e3a05e6e3d3a8e24d627cdb2cc53f23e90bad347 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 16 Nov 2017 15:51:24 +0100 Subject: [PATCH 64/86] Delete spies restore call --- test/unit/logic/transactions/pool.js | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 9e1948bd51f..a8c50e5b60d 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -51,7 +51,7 @@ describe('transactionPool', function () { secret: 'island pizza tilt scrap spend guilt one guitar range narrow rough hotel', } ]; - + var transactions = [ /* Type: 0 - Transmit funds.*/ node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), @@ -77,7 +77,7 @@ describe('transactionPool', function () { ['+' + testAccounts[2].account.publicKey,'+' + testAccounts[1].account.publicKey], [testAccounts[2].secret], 1, 2) ] ]; - + var invalidsTransactions = [ /* Type: 0 - Transmit funds account without enough credit.*/ node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000000, testAccounts[1].secret), @@ -111,7 +111,7 @@ describe('transactionPool', function () { ['+' + testAccounts[2].account.publicKey], [testAccounts[1].secret], 1, 1) ] ]; - + var hackedTransactions = [ /* Invalid signature */ { @@ -131,7 +131,7 @@ describe('transactionPool', function () { 'id': '16349767733713562311' } ]; - + // Set spies for logger var logger; var library; @@ -139,23 +139,14 @@ describe('transactionPool', function () { var poolTotals; var poolStorageTransactionsLimit; var dbSandbox; - + function resetSpiesState () { // Reset state of spies - logger.debug.reset(); logger.info.reset(); logger.warn.reset(); logger.error.reset(); } - - function restoreSpiesState () { - // Restore state of spies - logger.debug.restore(); - logger.info.restore(); - logger.warn.restore(); - logger.error.restore(); - } - + function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { var multisignatureTransaction = node.lisk.multisignature.createMultisignature(creatorSecret, creatorSecondSecret, keysgroup, min, lifetime); var signatures = []; @@ -237,7 +228,6 @@ describe('transactionPool', function () { }); after(function (done) { - restoreSpiesState(); dbSandbox.destroy(); node.appCleanup(done); }); From 6c48acb4713a64f06686c7fcc37c81d1ec0a9d33 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 16 Nov 2017 19:01:59 +0100 Subject: [PATCH 65/86] Add total in getUsage, adjust comments --- logic/transactions/pool.js | 14 +++++++------- test/unit/logic/transactions/pool.js | 11 +++++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index a378c5fee10..9f023a937d4 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -246,7 +246,7 @@ __private.processTransaction = function (transaction, sender, requester, waterCb }; /** - * Verifyes transaction. + * Verifies transaction. * @private * @implements {library.logic.transaction.verify} * @implements {__private.addInvalid} @@ -259,10 +259,8 @@ __private.verifyTransaction = function (transaction, sender, waterCb) { library.logic.transaction.verify(transaction, sender, function (err) { if (err) { __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); - } else { - return setImmediate(waterCb, null, transaction, sender); } + return setImmediate(waterCb, err, transaction, sender); }); }; @@ -378,7 +376,7 @@ __private.addToUnverified = function (transaction, broadcast, cb) { }; /** - * Adds transactions to pool list without checks. + * Adds transactions to pool list, increment counter only if transaction id is not present. * @private * @param {transaction} transaction * @param {Object} poolList @@ -544,6 +542,7 @@ TransactionPool.prototype.bind = function (accounts) { /** * Gets invalid, unverified, verified.pending and verified.ready counters. + * @implements {__private.countTransactionsPool} * @return {Object} unverified, pending, ready */ TransactionPool.prototype.getUsage = function () { @@ -551,7 +550,8 @@ TransactionPool.prototype.getUsage = function () { unverified: pool.unverified.count, pending: pool.verified.pending.count, ready: pool.verified.ready.count, - invalid: pool.invalid.count + invalid: pool.invalid.count, + total: __private.countTransactionsPool() }; }; @@ -804,7 +804,7 @@ TransactionPool.prototype.delete = function (id) { /** * Deletes transactions from pool lists and rechecks balance for ready transactions - * @implements {__private.delete} + * @implements {self.delete} * @param {string} id transaction id * @return {Array} names of cleared lists */ diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index a8c50e5b60d..98a0b375427 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -430,6 +430,7 @@ describe('transactionPool', function () { expect(totals.pending).to.equal(poolTotals.pending); expect(totals.ready).to.equal(poolTotals.ready); expect(totals.invalid).to.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -512,6 +513,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -632,6 +634,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -710,6 +713,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -825,6 +829,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); @@ -885,6 +890,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -953,6 +959,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); @@ -1015,6 +1022,7 @@ describe('transactionPool', function () { expect(totals.pending).to.be.equal(poolTotals.pending); expect(totals.ready).to.be.equal(poolTotals.ready); expect(totals.invalid).to.be.equal(poolTotals.invalid); + expect(totals.total).to.be.equal(poolTotals.unverified + poolTotals.pending + poolTotals.ready); done(); }); }); @@ -1239,9 +1247,8 @@ describe('transactionPool', function () { it('should be ok when pool totals are equal to pool storage limit', function (done) { var totals = transactionPool.getUsage(); - var currentStorage = totals.unverified + totals.pending + totals.ready; expect(totals).to.be.an('object'); - expect(currentStorage).to.equal(poolStorageTransactionsLimit); + expect(totals.total).to.equal(poolStorageTransactionsLimit); poolTotals = totals; done(); }); From 0e140c4931bb7413cd2840fb164d545628e640b4 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Thu, 16 Nov 2017 19:04:17 +0100 Subject: [PATCH 66/86] Add pool test to test index --- test/unit/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/index.js b/test/unit/index.js index 368bc1e8aed..a2953828adf 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -30,6 +30,7 @@ var pathFiles = [ './logic/transfer.js', './logic/vote.js', './logic/outTransfer.js', + './logic/transactions/pool.js', './modules/accounts.js', './modules/app.js', From e844d6146bf4534c7098f3e400946318268bfe1a Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 17 Nov 2017 12:41:48 +0100 Subject: [PATCH 67/86] Add peer parameter to processUnconfirmedTransaction --- modules/loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/loader.js b/modules/loader.js index 97f68875905..1a0dc189694 100644 --- a/modules/loader.js +++ b/modules/loader.js @@ -265,7 +265,7 @@ __private.loadTransactions = function (cb) { async.eachSeries(transactions, function (transaction, eachSeriesCb) { library.balancesSequence.add(function (cb) { transaction.bundled = true; - modules.transactions.processUnconfirmedTransaction(transaction, false, cb); + modules.transactions.processUnconfirmedTransaction('peer', transaction, false, cb); }, function (err) { if (err) { // TODO: Validate if must include error propagation. From 8df194a9e2a803aea97ce25d81ea1ea1fd1f5f60 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Fri, 17 Nov 2017 12:51:12 +0100 Subject: [PATCH 68/86] Delete transaction bundled flag --- modules/loader.js | 1 - modules/transport.js | 1 - 2 files changed, 2 deletions(-) diff --git a/modules/loader.js b/modules/loader.js index 1a0dc189694..37ecc26f2d5 100644 --- a/modules/loader.js +++ b/modules/loader.js @@ -264,7 +264,6 @@ __private.loadTransactions = function (cb) { function (transactions, waterCb) { async.eachSeries(transactions, function (transaction, eachSeriesCb) { library.balancesSequence.add(function (cb) { - transaction.bundled = true; modules.transactions.processUnconfirmedTransaction('peer', transaction, false, cb); }, function (err) { if (err) { diff --git a/modules/transport.js b/modules/transport.js index d2873a2069f..d9995616b4d 100644 --- a/modules/transport.js +++ b/modules/transport.js @@ -194,7 +194,6 @@ __private.receiveTransactions = function (query, peer, extraLogMessage, cb) { if (!transaction) { return setImmediate(eachSeriesCb, 'Unable to process transaction. Transaction is undefined.'); } - transaction.bundled = true; __private.receiveTransaction(transaction, peer, extraLogMessage, function (err) { if (err) { From 9e996872dc851dbf73938c8cf707274f41c0196f Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:01:04 +0100 Subject: [PATCH 69/86] Adjust bind to include only accounts --- modules/transactions.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/transactions.js b/modules/transactions.js index f28c9de474c..1f348459d1e 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -565,9 +565,7 @@ Transactions.prototype.onBind = function (scope) { }; library.logic.transactionPool.bind( - scope.accounts, - scope.transactions, - scope.loader + scope.accounts ); __private.assetTypes[transactionTypes.SEND].bind( scope.accounts From 0fadc2d4916d81ecba580b75e9cf05e5aed1622f Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:01:55 +0100 Subject: [PATCH 70/86] Update message descriptions --- test/unit/logic/transactions/pool.js | 43 +++++++++++----------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index 98a0b375427..e8ff6da6054 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -384,7 +384,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[0].id); + expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3.00001'].join(' ')); poolTotals.ready += 1; done(); @@ -408,8 +408,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[0].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -467,7 +466,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[1].id); + expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[1].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0.00001'].join(' ')); poolTotals.ready += 1; done(); @@ -491,8 +490,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[1].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -560,7 +558,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[2][0].id); + expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[2][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[2][0].senderId, 'balance: 0'].join(' ')); expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[2][1].id); expect(logger.error.args[1][1]).to.equal('Account is already a delegate'); @@ -612,8 +610,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[2].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -664,7 +661,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[3][0].id); + expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[3][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0.00001'].join(' ')); expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[3][1].id); expect(logger.error.args[1][1]).to.equal('Delegate not found'); @@ -691,8 +688,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[3].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -763,7 +759,7 @@ describe('transactionPool', function () { it('should be ok when process pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { - expect(logger.error.args[0][0]).to.equal('Failed to check balance transaction: ' + invalidsTransactions[4][0].id); + expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[4][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0.00001'].join(' ')); expect(logger.error.args[1][0]).to.equal('Failed to process unverified transaction: ' + invalidsTransactions[4][1].id); expect(logger.error.args[1][1]).to.equal('Failed to verify multisignature'); @@ -798,8 +794,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(completedSignatures.id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -807,8 +802,7 @@ describe('transactionPool', function () { it('should be ok when delete normal transaction without enough signatures to unverified', function (done) { var deletedTransaction = transactionPool.delete(transactions[4][1].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -876,8 +870,7 @@ describe('transactionPool', function () { it('should be ok when delete transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[4][2].id); - expect(deletedTransaction.length).to.equal(1); - expect(deletedTransaction[0]).to.equal('ready'); + expect(deletedTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); @@ -1267,9 +1260,7 @@ describe('transactionPool', function () { it('should be ok when delete a transaction from unverified', function (done) { var deleteTransaction = transactionPool.delete(invalidsTransactions[0].id); - expect(deleteTransaction).to.be.an('array').that.is.not.empty; - expect(deleteTransaction.length).to.equal(1); - expect(deleteTransaction[0]).to.equal('unverified'); + expect(deleteTransaction).to.equal('unverified'); done(); }); @@ -1285,7 +1276,7 @@ describe('transactionPool', function () { it('should fail when delete transaction that is not in pool', function (done) { var deleteTransaction = transactionPool.delete(transactions[0].id); - expect(deleteTransaction).to.be.an('array').that.is.empty; + expect(deleteTransaction).to.be.undefined; done(); }); }); @@ -1323,7 +1314,7 @@ describe('transactionPool', function () { }); it('should be ok when add type 2 transaction again to ready', function (done) { - transactionPool.addReady(allTransactions[2], function (err, cbtransaction) { + transactionPool.addReady([allTransactions[2]], function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); @@ -1350,9 +1341,7 @@ describe('transactionPool', function () { it('should be ok when delete transaction from ready', function (done) { var deleteTransaction = transactionPool.delete(transactions[0].id); - expect(deleteTransaction).to.be.an('array').that.is.not.empty; - expect(deleteTransaction.length).to.equal(1); - expect(deleteTransaction[0]).to.equal('ready'); + expect(deleteTransaction).to.equal('ready'); poolTotals.ready -= 1; done(); }); From fbde521d40fa385c5afc6a797f42cf7e668adad1 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:23:24 +0100 Subject: [PATCH 71/86] Rename function and variables to be more descriptives --- logic/transactions/pool.js | 84 ++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 9f023a937d4..e6a76d17a81 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -18,7 +18,7 @@ var __private = {}; var pool = {}; /** - * Initializes variables, sets bundled transaction pool timer and + * Initializes variables, sets cycle for transaction pool timer and * transaction pool expiry timer. * @memberof module:transactions * @class @@ -26,11 +26,13 @@ var pool = {}; * @implements {processPool} * @implements {expireTransactions} * @implements {resetInvalidTransactions} - * @param {Object} logger * @param {bus} bus * @param {Object} ed * @param {Transaction} transaction - transaction logic instance * @param {Account} account - account logic instance + * @param {Object} logger + * @param {Object} configPool - config values for pool + * @param {function} cbPool - Callback function. */ // Constructor function TransactionPool (bus, ed, transaction, account, logger, configPool, cbPool) { @@ -67,8 +69,8 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP broadcast: [] }; - // Pool cycle timer - function nextPoolCycle (cb) { + // Pool process timer + function nextProcessPool (cb) { self.processPool(function (err) { if (err) { library.logger.log('processPool transaction timer', err); @@ -77,10 +79,10 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP }); } - jobsQueue.register('transactionPoolNextCycle', nextPoolCycle, self.poolProcessInterval); + jobsQueue.register('transactionPoolNextProcess', nextProcessPool, library.config.transactions.pool.processInterval); // Transaction expiry timer - function nextExpiry (cb) { + function nextExpireTransactions (cb) { self.expireTransactions(function (err) { if (err) { library.logger.log('Transaction expiry timer', err); @@ -89,18 +91,20 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP }); } - jobsQueue.register('transactionPoolNextExpiry', nextExpiry, self.poolExpiryInterval); + jobsQueue.register('transactionPoolNextExpiryTransactions', nextExpireTransactions, library.config.transactions.pool.expiryInterval); // Invalid transactions reset timer - function nextReset () { + function nextInvalidTransactionsReset () { library.logger.debug(['Cleared invalid transactions:', self.resetInvalidTransactions()].join(' ')); } - jobsQueue.register('transactionPoolNextReset', nextReset, self.poolExpiryInterval); + jobsQueue.register('transactionPoolNextInvalidTransactionsReset', nextInvalidTransactionsReset, library.config.transactions.pool.expiryInterval); if (cbPool) { return setImmediate(cbPool, null, self); } + + self.transactionsTypesUnique = [transactionTypes.SIGNATURE, transactionTypes.DELEGATE, transactionTypes.MULTI]; } @@ -131,7 +135,7 @@ __private.getTransactionsFromPoolList = function (transactionsInPool, reverse, l * @param {Object} filter search criteria * @return {Objetc} transactions by pool list */ -__private.getAllPoolTransactionsByFilter = function (filter) { +__private.getAllTransactionsByFilter = function (filter) { var transactions = { unverified: _.filter(pool.unverified.transactions, filter), pending: _.filter(pool.verified.pending.transactions, filter), @@ -274,32 +278,33 @@ __private.verifyTransaction = function (transaction, sender, waterCb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.verifyTransactionTypeInPool = function (transaction, sender, waterCb) { +__private.verifyTransactionTypeInPool = function (transaction, sender, cb) { var senderTransactions = _.filter(pool.verified.ready.transactions, {'senderPublicKey': transaction.senderPublicKey}); - if (senderTransactions.length > 0 && transaction.type !== transactionTypes.SEND) { - return setImmediate(waterCb, 'Transaction type already in pool for sender', transaction, sender); + if (senderTransactions.length > 0 && self.transactionsTypesUnique.indexOf(transaction.type) !== -1) { + return setImmediate(cb, 'Transaction type already in pool for sender', transaction, sender); } - return setImmediate(waterCb, null, transaction, sender); + return setImmediate(cb, null, transaction, sender); }; /** * Adds transaction to verify pending or ready. * @private * @implements {__private.addToPoolList} - * @implements {__private.addReadyCheckBroadcast} + * @implements {__private.addReadyAndPrepareBroadcast} * @param {Object} transaction * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ __private.moveToVerified = function (transaction, cb) { - var receiveAtToTime = transaction.receivedAt.getTime(); - var timestampToTime = slots.getRealTime(transaction.timestamp); - if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAtToTime < timestampToTime) { + var receiveAt = transaction.receivedAt.getTime(); + var timestamp = slots.getRealTime(transaction.timestamp); + // Add transactions to pending if they are multisignature, they have signatures or timestamp is in future + if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAt < timestamp) { __private.addToPoolList(transaction, pool.verified.pending, cb); } else { - __private.addReadyCheckBroadcast(transaction, cb); + __private.addReadyAndPrepareBroadcast(transaction, cb); } }; @@ -392,13 +397,13 @@ __private.addToPoolList = function (transaction, poolList, cb) { }; /** - * Adds transactions to pool list without checks. + * Adds transactions to pool ready and to broadcast queue if broadcast flag is present. * @private * @param {transaction} transaction * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ -__private.addReadyCheckBroadcast = function (transaction, cb) { +__private.addReadyAndPrepareBroadcast = function (transaction, cb) { if (transaction.broadcast) { delete transaction.broadcast; pool.broadcast.push(transaction); @@ -447,6 +452,7 @@ __private.delete = function (id, poolList) { var transaction = poolList.transactions[id]; if (transaction !== undefined) { + poolList.transactions[id] = undefined; delete poolList.transactions[id]; poolList.count--; return true; @@ -501,7 +507,7 @@ __private.expireTransactionsFromList = function (poolList, cb) { * @param {transaction} transaction * @return {number} timeOut */ -__private.transactionTimeOut = function (transaction) { +__private.getTransactionTimeOut = function (transaction) { if (transaction.type === transactionTypes.MULTI) { return (transaction.asset.multisignature.lifetime * constants.secondsPerHour); } else if (Array.isArray(transaction.signatures)) { @@ -542,7 +548,7 @@ TransactionPool.prototype.bind = function (accounts) { /** * Gets invalid, unverified, verified.pending and verified.ready counters. - * @implements {__private.countTransactionsPool} + * @implements {__private.countTransactionsInPool} * @return {Object} unverified, pending, ready */ TransactionPool.prototype.getUsage = function () { @@ -551,7 +557,7 @@ TransactionPool.prototype.getUsage = function () { pending: pool.verified.pending.count, ready: pool.verified.ready.count, invalid: pool.invalid.count, - total: __private.countTransactionsPool() + total: __private.countTransactionsInPool() }; }; @@ -594,12 +600,12 @@ TransactionPool.prototype.get = function (id) { /** * Gets all transactions based on limited filters. * @implements {__private.getTransactionsFromPoolList} - * @implements {__private.getAllPoolTransactionsByFilter} + * @implements {__private.getAllTransactionsByFilter} * @param {string} filter * @param {Object} params * @return {[transaction]} transaction list based on filter. */ -TransactionPool.prototype.getAll = function (filter, params) { +TransactionPool.prototype.getAll = function (filter, params) { switch (filter) { case 'unverified': return __private.getTransactionsFromPoolList(pool.unverified.transactions, params.reverse, params.limit); @@ -608,13 +614,13 @@ TransactionPool.prototype.getAll = function (filter, params) { case 'ready': return __private.getTransactionsFromPoolList(pool.verified.ready.transactions, params.reverse, params.limit); case 'sender_id': - return __private.getAllPoolTransactionsByFilter({'senderId': params.id}); + return __private.getAllTransactionsByFilter({'senderId': params.id}); case 'sender_pk': - return __private.getAllPoolTransactionsByFilter({'senderPublicKey': params.publicKey}); + return __private.getAllTransactionsByFilter({'senderPublicKey': params.publicKey}); case 'recipient_id': - return __private.getAllPoolTransactionsByFilter({'recipientId': params.id}); + return __private.getAllTransactionsByFilter({'recipientId': params.id}); case 'recipient_pk': - return __private.getAllPoolTransactionsByFilter({'requesterPublicKey': params.publicKey}); + return __private.getAllTransactionsByFilter({'requesterPublicKey': params.publicKey}); default: return 'Invalid filter'; } @@ -626,15 +632,16 @@ TransactionPool.prototype.getAll = function (filter, params) { * @return {transaction[]} */ TransactionPool.prototype.getReady = function (limit) { - var r = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt'],['desc', 'asc']); - if (limit && limit < r.length) { - r.splice(limit); + var transactionsReady = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt', 'id'],['desc', 'asc', 'desc']); + if (limit && limit < transactionsReady.length) { + transactionsReady.splice(limit); } - return r; + return transactionsReady; }; /** - * Checks sender has enough credit to apply transaction. + * Checks if sender has enough credit to apply transaction. + * Balance - payments + receipts should be equal or greather than transaction fee + amount. * @param {transaction} transaction * @param {address} sender * @param {function} cb - Callback function. @@ -822,7 +829,7 @@ TransactionPool.prototype.sanitizeTransactions = function (transactions) { * @implements {__private.processUnverifiedTransaction} * @implements {self.checkBalance} * @implements {__private.moveToVerified} - * @implements {__private.addReadyCheckBroadcast} + * @implements {__private.addReadyAndPrepareBroadcast} * @param {function} cb * @return {setImmediateCallback} err | cb */ @@ -842,7 +849,7 @@ TransactionPool.prototype.processPool = function (cb) { } self.checkBalance(transaction, sender, function (err, balance) { if (err) { - library.logger.error('Failed to check balance transaction: ' + transaction.id, err); + library.logger.error('Failed to check balance for account related with transaction: ' + transaction.id, err); return setImmediate(eachSeriesCb); } return __private.moveToVerified(transaction, eachSeriesCb); @@ -856,7 +863,6 @@ TransactionPool.prototype.processPool = function (cb) { if (pool.verified.pending.count === 0) { return setImmediate(seriesCb); } - // process pool.verified.pending (multisig transactions signs), and take care // about moving transactions from `verified.pending` to `verified.ready` async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { @@ -866,7 +872,7 @@ TransactionPool.prototype.processPool = function (cb) { transaction.signatures.length >= transaction.asset.multisignature.min ) { __private.delete(transaction.id, pool.verified.pending); - __private.addReadyCheckBroadcast(transaction, eachSeriesCb); + __private.addReadyAndPrepareBroadcast(transaction, eachSeriesCb); } else { return setImmediate(eachSeriesCb); } From 4e3c0d80c68ff1cacf6f1d93e46a83a5ad5031db Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:25:53 +0100 Subject: [PATCH 72/86] Adjust callback description --- logic/transactions/pool.js | 52 ++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index e6a76d17a81..64acbdf3c3b 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -165,23 +165,23 @@ __private.transactionInPool = function (id) { * Checks if pool is ready to receive a new transaction and the incoming * transaction was not already processed by pool. * @private - * @implements {__private.countTransactionsPool} + * @implements {__private.countTransactionsInPool} * @implements {__private.transactionInPool} * @param {Object} transaction * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction */ -__private.checkPoolAvailability = function (transaction, waterCb) { - if (__private.countTransactionsPool() >= self.poolStorageTransactionsLimit) { - return setImmediate(waterCb, 'Transaction pool is full'); - } +__private.checkPoolAvailability = function (transaction, cb) { if (pool.invalid.transactions[transaction.id] !== undefined) { - return setImmediate(waterCb, 'Transaction is already processed as invalid: ' + transaction.id); + return setImmediate(cb, 'Transaction is already processed as invalid: ' + transaction.id); } if (__private.transactionInPool(transaction.id)) { - return setImmediate(waterCb, 'Transaction is already in pool: ' + transaction.id); + return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); + } + if (__private.countTransactionsInPool() >= library.config.transactions.pool.storageLimit) { + return setImmediate(cb, 'Transaction pool is full'); } - return setImmediate(waterCb, null, transaction); + return setImmediate(cb, null, transaction); }; /** @@ -193,9 +193,9 @@ __private.checkPoolAvailability = function (transaction, waterCb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.setAccountAndGet = function (transaction, waterCb) { - modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, function (err, cb) { - return setImmediate(waterCb, err, transaction, cb); +__private.setAccountAndGet = function (transaction, cb) { + modules.accounts.setAccountAndGet({publicKey: transaction.senderPublicKey}, function (err, cbAccount) { + return setImmediate(cb, err, transaction, cbAccount); }); }; @@ -239,13 +239,13 @@ __private.getRequester = function (transaction, sender, waterCb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.processTransaction = function (transaction, sender, requester, waterCb) { +__private.processTransaction = function (transaction, sender, requester, cb) { library.logic.transaction.process(transaction, sender, requester, function (err) { if (err) { __private.addInvalid(transaction.id); - return setImmediate(waterCb, err); + return setImmediate(cb, err); } - return setImmediate(waterCb, null, transaction, sender); + return setImmediate(cb, null, transaction, sender); }); }; @@ -259,12 +259,12 @@ __private.processTransaction = function (transaction, sender, requester, waterCb * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ -__private.verifyTransaction = function (transaction, sender, waterCb) { +__private.verifyTransaction = function (transaction, sender, cb) { library.logic.transaction.verify(transaction, sender, function (err) { if (err) { __private.addInvalid(transaction.id); } - return setImmediate(waterCb, err, transaction, sender); + return setImmediate(cb, err, transaction, sender); }); }; @@ -465,39 +465,37 @@ __private.delete = function (id, poolList) { * @private * @return {Number} Total = unverified + pending + ready */ -__private.countTransactionsPool = function () { +__private.countTransactionsInPool = function () { return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; }; /** - * Removes transactions if expired from pool list. + * Removes expired transactions from pool list. * @private - * @implements {__private.transactionTimeOut} + * @implements {__private.getTransactionTimeOut} * @implements {__private.delete} * @param {Object[]} poolList * @param {function} cb - Callback function * @return {setImmediateCallback} cb|error */ __private.expireTransactionsFromList = function (poolList, cb) { - async.eachSeries(poolList.transactions, function (transaction, eachSeriesCb) { + async.each(poolList.transactions, function (transaction, eachCb) { if (!transaction) { - return setImmediate(eachSeriesCb); + return setImmediate(eachCb); } var timeNow = Math.floor(Date.now() / 1000); - var timeOut = __private.transactionTimeOut(transaction); + var timeOut = __private.getTransactionTimeOut(transaction); // transaction.receivedAt is instance of Date var seconds = timeNow - Math.floor(transaction.receivedAt.getTime() / 1000); if (seconds > timeOut) { __private.delete(transaction.id, poolList); library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); - return setImmediate(eachSeriesCb); - } else { - return setImmediate(eachSeriesCb); } - }, function (err) { - return setImmediate(cb, err, null); + return setImmediate(eachCb); + }, function () { + return setImmediate(cb); }); }; From 38b3fa176c9e51ab2199155bdf943912a74aa000 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:28:28 +0100 Subject: [PATCH 73/86] Delete extra validations --- logic/transactions/pool.js | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 64acbdf3c3b..bd51bc1db8a 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -56,9 +56,6 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP }; self = this; - self.poolStorageTransactionsLimit = library.config.transactions.pool.storageLimit; - self.poolProcessInterval = library.config.transactions.pool.processInterval; - self.poolExpiryInterval = library.config.transactions.pool.expiryInterval; pool = { unverified: { transactions: {}, count: 0 }, verified:{ @@ -208,23 +205,23 @@ __private.setAccountAndGet = function (transaction, cb) { * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender, requester */ -__private.getRequester = function (transaction, sender, waterCb) { - var multisignatures = Array.isArray(sender.multisignatures) && sender.multisignatures.length; +__private.getRequester = function (transaction, sender, cb) { + var isMultisignature = Array.isArray(sender.multisignatures) && sender.multisignatures.length > 0; - if (multisignatures) { + if (isMultisignature) { transaction.signatures = transaction.signatures || []; } - if (sender && transaction.requesterPublicKey && multisignatures) { + if (sender && transaction.requesterPublicKey && isMultisignature) { modules.accounts.getAccount({publicKey: transaction.requesterPublicKey}, function (err, requester) { if (!requester) { - return setImmediate(waterCb, 'Requester not found'); + return setImmediate(cb, 'Requester not found'); } else { - return setImmediate(waterCb, null, transaction, sender, requester); + return setImmediate(cb, null, transaction, sender, requester); } }); } else { - return setImmediate(waterCb, null, transaction, sender, null); + return setImmediate(cb, null, transaction, sender, null); } }; @@ -735,17 +732,15 @@ TransactionPool.prototype.addFromPeer = function (transactions, broadcast, cb) { * Adds transactions to verified.ready pool list. * @implements {__private.addToPoolList} * @implements {delete} - * @param {transaction} transactions + * @param {[transaction]} transactions - Array of transactions * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ TransactionPool.prototype.addReady = function (transactions, cb) { - if (!Array.isArray(transactions)) { - transactions = [transactions]; - } var resetReceivedAt = new Date(); + async.eachSeries(transactions, function (transaction, eachSeriesCb) { - self.delete(transaction); + self.delete(transaction.id); transaction.receivedAt = resetReceivedAt; __private.addToPoolList(transaction, pool.verified.ready, eachSeriesCb); }, function (err) { From 4ba210bef09516dc848574f92880ae8cd29e8971 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:29:18 +0100 Subject: [PATCH 74/86] Adjust space in objects --- logic/transactions/pool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index bd51bc1db8a..349e386c59a 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -647,7 +647,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { var paymentTransactions; var receiptTransactions; - library.logic.account.get({ address: sender.address }, 'balance', function (err, account) { + library.logic.account.get({address: sender.address}, 'balance', function (err, account) { if (err) { return setImmediate(cb, err); } @@ -656,7 +656,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { account.balance = 0; } // total payments - paymentTransactions = self.getAll('sender_id', { id: sender.address }); + paymentTransactions = self.getAll('sender_id', {id: sender.address}); if (paymentTransactions.ready.length > 0) { paymentTransactions.ready.forEach(function (paymentTransaction) { if (paymentTransaction.amount) { @@ -667,7 +667,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { } // total receipts - receiptTransactions = self.getAll('recipient_id', { id: sender.address }); + receiptTransactions = self.getAll('recipient_id', {id: sender.address}); if (receiptTransactions.ready.length > 0) { receiptTransactions.ready.forEach(function (receiptTransaction) { if (receiptTransaction.type === transactionTypes.SEND) { From 9427212fc523900bc96b2faef306fb14bdedc1fa Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:30:41 +0100 Subject: [PATCH 75/86] Return string instead of array --- logic/transactions/pool.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 349e386c59a..45665183396 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -794,12 +794,11 @@ TransactionPool.prototype.delete = function (id) { clearedList.push(poolList[index]); } }); - if (clearedList.length > 0) { - if (clearedList.length > 1) { - library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transaction id:', id].join(' ')); - } + if (clearedList.length > 1) { + library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transaction id:', id].join(' ')); } - return clearedList; + + return clearedList[0] ? clearedList[0] : undefined; }; /** From e67c32a7b5ea8f6377baaa008cd7d3922f5bfb09 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Tue, 21 Nov 2017 16:32:10 +0100 Subject: [PATCH 76/86] Improve function efficiency --- logic/transactions/pool.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index 45665183396..bd4333b4ce6 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -907,8 +907,9 @@ TransactionPool.prototype.expireTransactions = function (cb) { */ TransactionPool.prototype.resetInvalidTransactions = function () { var counter = 0; + var transaction; - for (var transaction in pool.invalid.transactions) { + for (transaction in pool.invalid.transactions) { delete pool.invalid.transactions[transaction]; counter++; } From 338512878f0d5707b22bbc74d2da9c9409ab7630 Mon Sep 17 00:00:00 2001 From: Lucas Isasmendi Date: Wed, 22 Nov 2017 13:58:39 +0100 Subject: [PATCH 77/86] Restore processBlock call from generateBlock --- modules/blocks/process.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/blocks/process.js b/modules/blocks/process.js index cd2f3d6a795..6e106be115e 100644 --- a/modules/blocks/process.js +++ b/modules/blocks/process.js @@ -486,6 +486,7 @@ Process.prototype.generateBlock = function (keypair, timestamp, cb) { library.logger.error(e.stack); return setImmediate(cb, e); } + /* Apply this logic as part of 449 // Set block missed values block.id = library.logic.block.getId(block); block.height = lastBlock.height + 1; @@ -498,6 +499,10 @@ Process.prototype.generateBlock = function (keypair, timestamp, cb) { // Apply block - saveBlock: true modules.blocks.chain.applyBlock(block, true, cb); +*/ + // delete this logic as part of 449 + // Start block processing - broadcast: true, saveBlock: true + modules.blocks.verify.processBlock(block, true, cb, true); }; /** From 40ef399513682c4fea617d454d8d51f4ad8f9aec Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sat, 25 Nov 2017 21:32:18 +0100 Subject: [PATCH 78/86] Review config.json --- config.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/config.json b/config.json index e7e8265ff12..0abc726d125 100644 --- a/config.json +++ b/config.json @@ -110,12 +110,12 @@ "relayLimit": 2 }, "transactions": { - "maxTxsPerQueue": 1000, - "pool": { - "storageLimit": 4000, - "processInterval": 5000, - "expiryInterval": 25000 - } + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInterval": 25000 + } }, "forging": { "force": false, From 4d103b911ebea353d92c1ef814699787c9bfd36d Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 12:21:01 +0100 Subject: [PATCH 79/86] Review logic/transaction.js --- logic/transaction.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/logic/transaction.js b/logic/transaction.js index 8e898f2b2aa..1fec7584fea 100644 --- a/logic/transaction.js +++ b/logic/transaction.js @@ -529,14 +529,14 @@ Transaction.prototype.verify = function (transaction, sender, requester, cb) { } // Check confirmed sender balance - /** this check will be done in transaction pool + /* TODO: This check will be done in the transaction pool var amount = new bignum(trs.amount.toString()).plus(trs.fee.toString()); var senderBalance = this.checkBalance(amount, 'balance', trs, sender); if (senderBalance.exceeded) { return setImmediate(cb, senderBalance.error); } - */ + */ // Check timestamp if (slots.getSlotNumber(transaction.timestamp) > slots.getSlotNumber()) { @@ -662,8 +662,8 @@ Transaction.prototype.apply = function (transaction, block, sender, cb) { } // Check confirmed sender balance + // TODO: Check if this is done by the transaction pool in all the scenarios var amount = new bignum(transaction.amount.toString()).plus(transaction.fee.toString()); - // TODO: check if this is done by pool in all the scenarios var senderBalance = this.checkBalance(amount, 'balance', transaction, sender); if (senderBalance.exceeded) { From 8f441b17fa911433096bb05611dbd2d8501fea69 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 13:42:06 +0100 Subject: [PATCH 80/86] Review logic/transactions/pool.js --- logic/transactions/pool.js | 272 ++++++++++++++++++++----------------- 1 file changed, 146 insertions(+), 126 deletions(-) diff --git a/logic/transactions/pool.js b/logic/transactions/pool.js index bd4333b4ce6..4803d480775 100644 --- a/logic/transactions/pool.js +++ b/logic/transactions/pool.js @@ -11,27 +11,26 @@ var bignum = require('../../helpers/bignum.js'); var slots = require('../../helpers/slots.js'); // Private fields -var modules; +var modules; var library; var self; var __private = {}; var pool = {}; /** - * Initializes variables, sets cycle for transaction pool timer and - * transaction pool expiry timer. + * Initializes variables and starts processPool/expiry/invalid timers. * @memberof module:transactions * @class - * @classdesc Main TransactionPool logic. + * @classdesc Transaction pool logic. * @implements {processPool} * @implements {expireTransactions} * @implements {resetInvalidTransactions} - * @param {bus} bus - * @param {Object} ed - * @param {Transaction} transaction - transaction logic instance - * @param {Account} account - account logic instance - * @param {Object} logger - * @param {Object} configPool - config values for pool + * @param {bus} bus - Bus instance. + * @param {Object} ed - Ed instance. + * @param {object} transaction - Transaction logic instance. + * @param {Account} account - Account logic instance. + * @param {Object} logger - Logger instance. + * @param {Object} configPool - Config values for the pool. * @param {function} cbPool - Callback function. */ // Constructor @@ -54,6 +53,7 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP } }, }; + self = this; pool = { @@ -70,7 +70,7 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP function nextProcessPool (cb) { self.processPool(function (err) { if (err) { - library.logger.log('processPool transaction timer', err); + library.logger.log('ProcessPool transaction timer', err); } return setImmediate(cb); }); @@ -107,12 +107,12 @@ function TransactionPool (bus, ed, transaction, account, logger, configPool, cbP // Private /** - * Gets all or limited number of transactions from input object list and returns ordered array. + * Gets transactions from a pool list. * @private - * @param {transaction{}} transactions - * @param {boolean} reverse - * @param {number} limit - * @return {transaction[]} + * @param {object} transactionsInPool - Name of pool list. + * @param {boolean} reverse - Reverse order of results. + * @param {number} limit - Limit applied to results. + * @return {array} Of ordered transactions in pool list. */ __private.getTransactionsFromPoolList = function (transactionsInPool, reverse, limit) { var transactions = _.orderBy(transactionsInPool, ['receivedAt'],['asc']); @@ -127,10 +127,10 @@ __private.getTransactionsFromPoolList = function (transactionsInPool, reverse, l }; /** - * Gets transactions from all pool lists based on filter. + * Gets all transactions from the pool lists matching a search criteria. * @private - * @param {Object} filter search criteria - * @return {Objetc} transactions by pool list + * @param {Object} filter - Search criteria. + * @return {Object} Of pool lists with matched transactions. */ __private.getAllTransactionsByFilter = function (filter) { var transactions = { @@ -143,9 +143,9 @@ __private.getAllTransactionsByFilter = function (filter) { }; /** - * Returns true if the id is present in at least one of the pool lists transactions. + * Checks if a transaction id is present in at least one of the pool lists. * @private - * @param {string} id + * @param {string} id - Transaction id. * @return {boolean} */ __private.transactionInPool = function (id) { @@ -159,12 +159,12 @@ __private.transactionInPool = function (id) { }; /** - * Checks if pool is ready to receive a new transaction and the incoming - * transaction was not already processed by pool. + * Checks if the pool is ready to receive a new transaction, + * and whether the received transaction was already processed. * @private * @implements {__private.countTransactionsInPool} * @implements {__private.transactionInPool} - * @param {Object} transaction + * @param {object} transaction - Transaction object. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction */ @@ -172,21 +172,24 @@ __private.checkPoolAvailability = function (transaction, cb) { if (pool.invalid.transactions[transaction.id] !== undefined) { return setImmediate(cb, 'Transaction is already processed as invalid: ' + transaction.id); } + if (__private.transactionInPool(transaction.id)) { return setImmediate(cb, 'Transaction is already in pool: ' + transaction.id); } + if (__private.countTransactionsInPool() >= library.config.transactions.pool.storageLimit) { return setImmediate(cb, 'Transaction pool is full'); } + return setImmediate(cb, null, transaction); }; /** - * Obtains sender from accounts table, if address does not exists, - * returns a default account object. + * Obtains the transaction sender from the accounts table. + * If the sender's address does not exist, returns a default account object. * @private * @implements {modules.accounts.setAccountAndGet} - * @param {Object} transaction + * @param {object} transaction - Transaction object. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ @@ -197,11 +200,11 @@ __private.setAccountAndGet = function (transaction, cb) { }; /** - * Obtains requester from accounts table + * Obtains the transaction requester from the accounts table. * @private * @implements {modules.accounts.getAccount} - * @param {Object} transaction - * @param {Object} sender + * @param {object} transaction - Transaction object. + * @param {Object} sender - Sender account. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender, requester */ @@ -226,13 +229,13 @@ __private.getRequester = function (transaction, sender, cb) { }; /** - * Process transaction. + * Processes a transaction. * @private * @implements {library.logic.transaction.process} * @implements {__private.addInvalid} - * @param {Object} transaction - * @param {Object} sender - * @param {Object} requester + * @param {object} transaction - Transaction object. + * @param {Object} sender - Sender account. + * @param {Object} requester - Requester account. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ @@ -241,18 +244,19 @@ __private.processTransaction = function (transaction, sender, requester, cb) { if (err) { __private.addInvalid(transaction.id); return setImmediate(cb, err); - } + } + return setImmediate(cb, null, transaction, sender); }); }; /** - * Verifies transaction. + * Verifies a transaction. * @private * @implements {library.logic.transaction.verify} * @implements {__private.addInvalid} - * @param {Object} transaction - * @param {Object} sender + * @param {object} transaction - Transaction object. + * @param {Object} sender - Sender account. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ @@ -261,17 +265,18 @@ __private.verifyTransaction = function (transaction, sender, cb) { if (err) { __private.addInvalid(transaction.id); } + return setImmediate(cb, err, transaction, sender); }); }; /** - * Verifies if transaction type is repeated into pool from same sender. + * Verifies if a transaction type is already in the pool from the same sender. * @private * @implements {library.logic.transaction.verify} * @implements {__private.addInvalid} - * @param {Object} transaction - * @param {Object} sender + * @param {object} transaction - Transaction object. + * @param {Object} sender - Sender account. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb, transaction, sender */ @@ -286,19 +291,20 @@ __private.verifyTransactionTypeInPool = function (transaction, sender, cb) { }; /** - * Adds transaction to verify pending or ready. + * Adds a transaction to the verify, pending or ready pool list. * @private * @implements {__private.addToPoolList} * @implements {__private.addReadyAndPrepareBroadcast} - * @param {Object} transaction + * @param {object} transaction - Transaction object. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ __private.moveToVerified = function (transaction, cb) { - var receiveAt = transaction.receivedAt.getTime(); + var receivedAt = transaction.receivedAt.getTime(); var timestamp = slots.getRealTime(transaction.timestamp); - // Add transactions to pending if they are multisignature, they have signatures or timestamp is in future - if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receiveAt < timestamp) { + + // Add transactions to pending if they of type multisignature, they have signatures or timestamp is in future + if (transaction.type === transactionTypes.MULTI || Array.isArray(transaction.signatures) || receivedAt < timestamp) { __private.addToPoolList(transaction, pool.verified.pending, cb); } else { __private.addReadyAndPrepareBroadcast(transaction, cb); @@ -306,9 +312,9 @@ __private.moveToVerified = function (transaction, cb) { }; /** - * Adds transactions to verified pool list. - * Checks if transaction is in pool, pool limit, performs basic transaction validations - * and advanced transaction validations: verify and check balance. + * Adds a transaction to the verified pool list. + * Checks if the transaction is in the pool, or if pool limit has been reached. + * Performs basic and advanced transaction validations: verify and check balance. * @private * @implements {__private.checkPoolAvailability} * @implements {__private.setAccountAndGet} @@ -316,8 +322,8 @@ __private.moveToVerified = function (transaction, cb) { * @implements {__private.processTransaction} * @implements {__private.verifyTransaction} * @implements {__private.moveToVerified} - * @param {Transaction} transaction - * @param {boolean} broadcast + * @param {object} transaction - Transaction object. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -345,15 +351,16 @@ __private.addToVerified = function (transaction, broadcast, cb) { }; /** - * Adds transactions to unverified pool list. - * Checks if transaction is in pool, pool limit and performs basic transaction validations. + * Adds a transaction to the unverified pool list. + * Checks if the transaction is in the pool, or if pool limit has been reached. + * Performs basic transaction validations. * @private * @implements {__private.checkPoolAvailability} * @implements {__private.setAccountAndGet} * @implements {__private.getAccount} * @implements {__private.processTransaction} - * @param {Transaction} transaction - * @param {boolean} broadcast + * @param {object} transaction - Transaction object. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -378,10 +385,11 @@ __private.addToUnverified = function (transaction, broadcast, cb) { }; /** - * Adds transactions to pool list, increment counter only if transaction id is not present. + * Adds a transaction to the pool list. + * Increments pool list counter only if transaction id is not present. * @private - * @param {transaction} transaction - * @param {Object} poolList + * @param {object} transaction - Transaction object. + * @param {Object} poolList - Pool list object. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -394,9 +402,10 @@ __private.addToPoolList = function (transaction, poolList, cb) { }; /** - * Adds transactions to pool ready and to broadcast queue if broadcast flag is present. + * Adds a transaction to the ready pool list. + * Adds the transaction to the broadcast queue if its broadcast flag is true. * @private - * @param {transaction} transaction + * @param {object} transaction - Transaction object. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -409,10 +418,10 @@ __private.addReadyAndPrepareBroadcast = function (transaction, cb) { }; /** - * Creates signature based on multisignature transaction and secret. + * Creates a signature for the given multisignature transaction and secret. * @private - * @param {transaction} transaction - * @param {String} secret + * @param {object} transaction - Transaction object. + * @param {String} secret - Secret passphrase, * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -420,18 +429,19 @@ __private.createSignature = function (transaction, secret, cb) { var hash = crypto.createHash('sha256').update(secret, 'utf8').digest(); var keypair = library.ed.makeKeypair(hash); var publicKey = keypair.publicKey.toString('hex'); - + if (transaction.asset.multisignature.keysgroup.indexOf('+' + publicKey) === -1) { return setImmediate(cb, 'Permission to sign transaction denied'); } + var signature = library.logic.transaction.multisign(keypair, transaction); return setImmediate(cb, null, signature); }; /** - * Adds transaction id to invalid pool list. + * Adds a transaction id to the invalid pool list. * @private - * @param {string} id + * @param {string} id - Transaction id. */ __private.addInvalid = function (id) { pool.invalid.transactions[id] = true; @@ -439,11 +449,11 @@ __private.addInvalid = function (id) { }; /** - * Deletes id from pool list. + * Deletes a transaction by id from a pool list. * @private - * @param {string} id - * @param {Object} poolList - * @return {boolean} true if transaction id is on the list and was deleted + * @param {string} id - Transaction id. + * @param {Object} poolList - Pool list object. + * @return {boolean} True if transaction id was found and deleted. */ __private.delete = function (id, poolList) { var transaction = poolList.transactions[id]; @@ -453,26 +463,27 @@ __private.delete = function (id, poolList) { delete poolList.transactions[id]; poolList.count--; return true; + } else { + return false; } - return false; }; /** * Sums unverified, verified.pending and verified.ready counters. * @private - * @return {Number} Total = unverified + pending + ready + * @return {Number} Of unverified + pending + ready. */ __private.countTransactionsInPool = function () { return pool.unverified.count + pool.verified.pending.count + pool.verified.ready.count; }; /** - * Removes expired transactions from pool list. + * Removes expired transactions from a pool list. * @private * @implements {__private.getTransactionTimeOut} * @implements {__private.delete} - * @param {Object[]} poolList - * @param {function} cb - Callback function + * @param {Object} poolList - Pool list object. + * @param {function} cb - Callback function. * @return {setImmediateCallback} cb|error */ __private.expireTransactionsFromList = function (poolList, cb) { @@ -490,6 +501,7 @@ __private.expireTransactionsFromList = function (poolList, cb) { __private.delete(transaction.id, poolList); library.logger.info('Expired transaction: ' + transaction.id + ' received at: ' + transaction.receivedAt.toUTCString()); } + return setImmediate(eachCb); }, function () { return setImmediate(cb); @@ -497,10 +509,10 @@ __private.expireTransactionsFromList = function (poolList, cb) { }; /** - * Calculates timeout based on transaction. + * Calculates expiry timeout for a transaction based on type. * @private - * @param {transaction} transaction - * @return {number} timeOut + * @param {object} transaction - Transaction object. + * @return {number} Of transaction timeout. */ __private.getTransactionTimeOut = function (transaction) { if (transaction.type === transactionTypes.MULTI) { @@ -513,12 +525,12 @@ __private.getTransactionTimeOut = function (transaction) { }; /** - * Gets sender account, and verifies transaction. + * Gets the transaction sender from the accounts table, and then verifies the transaction. * @private * @implements {__private.setAccountAndGet} * @implements {__private.verifyTransaction} - * @param {transaction} transaction - * @param {function} cb - Callback function + * @param {object} transaction - Transaction object. + * @param {function} cb - Callback function. * @returns {setImmediateCallback} errors | sender */ __private.processUnverifiedTransaction = function (transaction, cb) { @@ -533,7 +545,7 @@ __private.processUnverifiedTransaction = function (transaction, cb) { // Public methods /** * Bounds input parameters to private variable modules. - * @param {Accounts} accounts + * @param {Accounts} accounts - Accounts module instance. */ TransactionPool.prototype.bind = function (accounts) { modules = { @@ -557,9 +569,9 @@ TransactionPool.prototype.getUsage = function () { }; /** - * Gets transaction based on transaction id. + * Gets a transaction by id. * Checks all pool lists: unverified, pending, ready. - * @param {string} id + * @param {string} id - Transaction id. * @return {Object} transaction, status */ TransactionPool.prototype.get = function (id) { @@ -578,7 +590,7 @@ TransactionPool.prototype.get = function (id) { status: 'pending' }; } - + transaction = pool.verified.ready.transactions[id]; if (transaction !== undefined) { return { @@ -586,6 +598,7 @@ TransactionPool.prototype.get = function (id) { status: 'ready' }; } + return { transaction: undefined, status: 'Transaction not in pool' @@ -593,12 +606,12 @@ TransactionPool.prototype.get = function (id) { }; /** - * Gets all transactions based on limited filters. + * Gets all transactions matching a search criteria. * @implements {__private.getTransactionsFromPoolList} * @implements {__private.getAllTransactionsByFilter} - * @param {string} filter - * @param {Object} params - * @return {[transaction]} transaction list based on filter. + * @param {string} filter - Search criteria. + * @param {Object} params - Parameters given to each pool list. + * @return {array} Of matched transactions. */ TransactionPool.prototype.getAll = function (filter, params) { switch (filter) { @@ -623,22 +636,24 @@ TransactionPool.prototype.getAll = function (filter, params) { /** * Gets ready transactions ordered by fee and received time. - * @param {number} limit + * @param {number} limit - Limit applied to results. * @return {transaction[]} */ TransactionPool.prototype.getReady = function (limit) { var transactionsReady = _.orderBy(pool.verified.ready.transactions, ['fee', 'receivedAt', 'id'],['desc', 'asc', 'desc']); + if (limit && limit < transactionsReady.length) { transactionsReady.splice(limit); } + return transactionsReady; }; /** - * Checks if sender has enough credit to apply transaction. - * Balance - payments + receipts should be equal or greather than transaction fee + amount. - * @param {transaction} transaction - * @param {address} sender + * Checks if a sender has enough funds to apply a transaction. + * Balance - (debits + credits) should be equal or greather than transaction fee + amount. + * @param {object} transaction - Transaction object. + * @param {address} sender - Sender address. * @param {function} cb - Callback function. * @return {setImmediateCallback} err, transactions */ @@ -651,11 +666,13 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { if (err) { return setImmediate(cb, err); } + if (account === null) { account = {}; account.balance = 0; } - // total payments + + // Total payments paymentTransactions = self.getAll('sender_id', {id: sender.address}); if (paymentTransactions.ready.length > 0) { paymentTransactions.ready.forEach(function (paymentTransaction) { @@ -665,8 +682,8 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { poolBalance = poolBalance.minus(paymentTransaction.fee.toString()); }); } - - // total receipts + + // Total receipts receiptTransactions = self.getAll('recipient_id', {id: sender.address}); if (receiptTransactions.ready.length > 0) { receiptTransactions.ready.forEach(function (receiptTransaction) { @@ -676,7 +693,7 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { }); } - // total balance + // Total balance var balance = new bignum(account.balance.toString()); balance = balance.plus(poolBalance); @@ -700,8 +717,8 @@ TransactionPool.prototype.checkBalance = function (transaction, sender, cb) { /** * Validates a transaction and adds it to the verified pool list. * @implements {__private.addToVerified} - * @param {transaction} transaction - * @param {boolean} broadcast + * @param {object} transaction - Transaction object. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -710,10 +727,10 @@ TransactionPool.prototype.addFromPublic = function (transaction, broadcast, cb) }; /** - * Adds transactions to unverified pool list. + * Adds an array of transactions to the unverified pool list. * @implements {__private.addToUnverified} - * @param {transaction} transactions - * @param {boolean} broadcast + * @param {array} transactions - Array of transactions. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -721,6 +738,7 @@ TransactionPool.prototype.addFromPeer = function (transactions, broadcast, cb) { if (!Array.isArray(transactions)) { transactions = [transactions]; } + async.eachSeries(transactions, function (transaction, cb) { __private.addToUnverified(transaction, broadcast, cb); }, function (err) { @@ -729,10 +747,10 @@ TransactionPool.prototype.addFromPeer = function (transactions, broadcast, cb) { }; /** - * Adds transactions to verified.ready pool list. + * Adds an array of transactions to the verified.ready pool list. * @implements {__private.addToPoolList} * @implements {delete} - * @param {[transaction]} transactions - Array of transactions + * @param {[transaction]} transactions - Array of transactions. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -749,10 +767,10 @@ TransactionPool.prototype.addReady = function (transactions, cb) { }; /** - * Creates and adds signature to multisignature transaction. + * Creates and adds a signature to a multisignature transaction. * @implements {__private.createSignature} - * @param {String} transactionId transaction id - * @param {String} secret secret + * @param {String} transactionId - Transaction id. + * @param {String} secret - Secret passphrase. * @param {function} cb - Callback function. * @return {setImmediateCallback} error | cb */ @@ -764,7 +782,7 @@ TransactionPool.prototype.addSignature = function (transactionId, secret, cb) { return setImmediate(cb, 'Transaction not in pool'); } - // TODO: replace with checkSignature to reflect API 1.0.18 functionality + // TODO: Replace with checkSignature to reflect API 1.0.18 functionality __private.createSignature(multisignatureTransaction, secret, function (err, signature) { if (err) { return setImmediate(cb, err); @@ -773,17 +791,17 @@ TransactionPool.prototype.addSignature = function (transactionId, secret, cb) { library.logger.error(['Transaction already signed:', transactionId].join(' ')); return setImmediate(cb, 'Transaction already signed'); } - + multisignatureTransaction.signatures.push(signature); return setImmediate(cb); }); }; /** - * Deletes transaction from pool list. + * Deletes a transaction from the pool lists by id. * @implements {__private.delete} - * @param {string} id transaction id - * @return {Array} names of cleared lists + * @param {string} id - Transaction id. + * @return {Array} Of cleared pool lists. */ TransactionPool.prototype.delete = function (id) { var clearedList = []; @@ -794,6 +812,7 @@ TransactionPool.prototype.delete = function (id) { clearedList.push(poolList[index]); } }); + if (clearedList.length > 1) { library.logger.debug(['Cleared duplicated transaction in pool list:', clearedList, 'transaction id:', id].join(' ')); } @@ -802,10 +821,10 @@ TransactionPool.prototype.delete = function (id) { }; /** - * Deletes transactions from pool lists and rechecks balance for ready transactions + * Deletes transactions from pool lists, and rechecks balance for ready transactions. * @implements {self.delete} - * @param {string} id transaction id - * @return {Array} names of cleared lists + * @param {string} id - Transaction id. + * @return {Array} Of cleared pool lists. */ TransactionPool.prototype.sanitizeTransactions = function (transactions) { transactions.forEach(function (transaction) { @@ -814,15 +833,15 @@ TransactionPool.prototype.sanitizeTransactions = function (transactions) { }; /** - * Pulls transactions from unverified, perform verifications and if successful - * push to either verified.pending (when transaction is multisign or timestamp is in - * future) or verified.ready otherwise. + * Pulls transactions from unverified, performs verifications, and if successful + * pushes them to either verified.pending (when transaction is multisign or timestamp is in + * future), otherwise to verified.ready. * @implements {__private.delete} * @implements {__private.processUnverifiedTransaction} * @implements {self.checkBalance} * @implements {__private.moveToVerified} * @implements {__private.addReadyAndPrepareBroadcast} - * @param {function} cb + * @param {function} cb - Callback function. * @return {setImmediateCallback} err | cb */ TransactionPool.prototype.processPool = function (cb) { @@ -855,12 +874,12 @@ TransactionPool.prototype.processPool = function (cb) { if (pool.verified.pending.count === 0) { return setImmediate(seriesCb); } - // process pool.verified.pending (multisig transactions signs), and take care - // about moving transactions from `verified.pending` to `verified.ready` + // Process pool.verified.pending (multisig transactions signs), and moves + // transactions from `verified.pending` to `verified.ready` async.eachSeries(pool.verified.pending.transactions, function (transaction, eachSeriesCb) { // Check multisignatures - if (transaction.type === transactionTypes.MULTI && - Array.isArray(transaction.signatures) && + if (transaction.type === transactionTypes.MULTI && + Array.isArray(transaction.signatures) && transaction.signatures.length >= transaction.asset.multisignature.min ) { __private.delete(transaction.id, pool.verified.pending); @@ -880,13 +899,12 @@ TransactionPool.prototype.processPool = function (cb) { }; /** - * Expires transactions. + * Expires transactions according to their individual timeout. * @implements {__private.expireTransactionsFromList} * @param {function} cb - Callback function. * @return {setImmediateCallback} error, cb */ TransactionPool.prototype.expireTransactions = function (cb) { - async.series([ function (seriesCb) { __private.expireTransactionsFromList(pool.unverified, seriesCb); @@ -904,6 +922,7 @@ TransactionPool.prototype.expireTransactions = function (cb) { /** * Reset invalid transactions. + * @return {number} Of invalid transactions reset. */ TransactionPool.prototype.resetInvalidTransactions = function () { var counter = 0; @@ -913,6 +932,7 @@ TransactionPool.prototype.resetInvalidTransactions = function () { delete pool.invalid.transactions[transaction]; counter++; } + pool.invalid.count = 0; return counter; }; From 19bab75329296d94e56421872c5ca729ec74da07 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 14:27:05 +0100 Subject: [PATCH 81/86] Review modules/blocks/chain.js --- modules/blocks/chain.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/blocks/chain.js b/modules/blocks/chain.js index c9c90da5e0a..4131fc6862b 100644 --- a/modules/blocks/chain.js +++ b/modules/blocks/chain.js @@ -334,13 +334,12 @@ Chain.prototype.applyBlock = function (block, saveBlock, cb) { modules.blocks.isActive.set(true); async.series({ - // TODO: new series: after validate block, validate each transaction and insert into database, + // TODO: New series: after validating block, validate each transaction and insert into database, // sanitize transactionPool: delete transaction.id and if sender or receipt are in ready pool // list, checkbalance again - applyTransactions: function (seriesCb) { async.eachSeries(block.transactions, function (transaction, eachSeriesCb) { - // TODO: improve transaction to avoid call getAccount to get sender address + // TODO: Improve transaction to avoid call getAccount to get sender address modules.accounts.getAccount({publicKey: transaction.senderPublicKey}, function (err, sender) { if (err) { // Fatal error, memory tables will be inconsistent From 7eed0c11039d4425e2f0a33a42be1288a50c4e02 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 13:42:33 +0100 Subject: [PATCH 82/86] Review modules/blocks/process.js --- modules/blocks/process.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/blocks/process.js b/modules/blocks/process.js index 6e106be115e..b81d829ac3b 100644 --- a/modules/blocks/process.js +++ b/modules/blocks/process.js @@ -486,7 +486,8 @@ Process.prototype.generateBlock = function (keypair, timestamp, cb) { library.logger.error(e.stack); return setImmediate(cb, e); } - /* Apply this logic as part of 449 + + /* TODO: Apply this logic as part of #449 // Set block missed values block.id = library.logic.block.getId(block); block.height = lastBlock.height + 1; @@ -494,13 +495,15 @@ Process.prototype.generateBlock = function (keypair, timestamp, cb) { // Delete default properties var blockReduced = modules.blocks.verify.deleteBlockProperties(block); var serializedBlockReduced = bson.serialize(blockReduced); + // Broadcast block - broadcast: true modules.blocks.chain.broadcastReducedBlock(serializedBlockReduced, block.id, true); // Apply block - saveBlock: true modules.blocks.chain.applyBlock(block, true, cb); -*/ - // delete this logic as part of 449 + */ + + // TODO: Delete this logic as part of #449 // Start block processing - broadcast: true, saveBlock: true modules.blocks.verify.processBlock(block, true, cb, true); }; From 79bd4883eb93e07f7a10b34a5c11564e59f25c04 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 13:43:01 +0100 Subject: [PATCH 83/86] Review modules/delegates.js --- modules/delegates.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/delegates.js b/modules/delegates.js index fa133ade763..2983a531c4e 100644 --- a/modules/delegates.js +++ b/modules/delegates.js @@ -415,7 +415,7 @@ __private.loadDelegates = function (cb) { Delegates.prototype.generateDelegateList = function (cb) { library.db.query(sql.delegateList).then(function (result) { __private.delegatesList = result[0].list; - // TODO: wait 0.9.10 backport to 1.0.0 to get delegate list + // TODO: Wait for 0.9.10 backport to 1.0.0 to get delegate list return setImmediate(cb, null, __private.delegatesList); }).catch(function (err) { return setImmediate(cb, err); From 55d6b9fe1142e7b77ffb5706a8c0d0ab2c68772e Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 13:48:24 +0100 Subject: [PATCH 84/86] Review modules/transactions.js --- modules/transactions.js | 136 ++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/modules/transactions.js b/modules/transactions.js index 1f348459d1e..0a41f475b0c 100644 --- a/modules/transactions.js +++ b/modules/transactions.js @@ -25,8 +25,7 @@ var self; __private.assetTypes = {}; /** - * Initializes library with scope content and generates a Transfer instance - * and a TransactionPool instance. + * Initializes library with scope content and generates a Transfer instance. * Calls logic.transaction.attachAssetType(). * @memberof module:transactions * @class @@ -61,9 +60,9 @@ function Transactions (cb, scope) { // Private methods /** - * Counts totals and gets transaction list from `trs_list` view. + * Counts totals and gets a transaction list from the db. * @private - * @param {Object} filter + * @param {Object} filter - Filter object. * @param {function} cb - Callback function. * @returns {setImmediateCallback} error | data: {transactions, count} */ @@ -245,10 +244,10 @@ __private.getAssetForIdsBasedOnType = function (ids, type) { }; /** - * Gets transaction by calling parameter method. + * Gets a transaction from the pool. * @private - * @param {Object} method - * @param {Object} req + * @param {Object} method - Pool list method. + * @param {Object} req - Request object. * @param {function} cb - Callback function. * @returns {setImmediateCallback} error | data: {transaction} */ @@ -269,11 +268,11 @@ __private.getPooledTransaction = function (method, req, cb) { }; /** - * Gets transactions by calling parameter method. + * Gets pooled transactions. * Filters by senderPublicKey or address if they are present. * @private - * @param {Object} method - * @param {Object} req + * @param {Object} method - Pool list method. + * @param {Object} req - Request object. * @param {function} cb - Callback function. * @returns {setImmediateCallback} error | data: {transactions, count} */ @@ -304,9 +303,9 @@ __private.getPooledTransactions = function (method, req, cb) { // Public methods /** - * Check if transaction is in pool. + * Checks if a transaction is in the pool. * @implements {transactionPool.get} - * @param {string} id + * @param {string} id - Transaction id. * @return {boolean} False if transaction not in pool. */ Transactions.prototype.transactionInPool = function (id) { @@ -315,10 +314,10 @@ Transactions.prototype.transactionInPool = function (id) { }; /** - * Gets transaction from pool and check if is in pending signature list. + * Gets a transaction from the pool, and checks if it's pending signatures. * @implements {transactionPool.get} - * @param {string} id - * @return {transaction|undefined} Calls transactionPool.getMultisignatureTransaction + * @param {string} id - Transaction id. + * @return {transaction|undefined} Transaction object or undefined. */ Transactions.prototype.getMultisignatureTransaction = function (id) { var transaction = library.logic.transactionPool.get(id); @@ -326,75 +325,74 @@ Transactions.prototype.getMultisignatureTransaction = function (id) { }; /** - * Gets unconfirmed transactions based on limit. + * Gets unconfirmed transactions, with a limit option. * @implements {transactionPool.getReady} - * @param {number} limit - * @return {transaction[]} + * @param {number} limit - Limit applied to results. + * @return {transaction[]} Calls transactionPool.getReady */ Transactions.prototype.getUnconfirmedTransactionList = function (limit) { return library.logic.transactionPool.getReady(limit); }; /** - * Gets queued transactions based on limit and reverse option. + * Gets queued transactions, with limit and reverse options. * @implements {transactionPool.getAll} - * @param {boolean} reverse - * @param {number} limit - * @return {transaction[]} + * @param {boolean} reverse - Reverse order of results. + * @param {number} limit - Limit applied to results. + * @return {transaction[]} Calls transactionPool.getAll */ Transactions.prototype.getQueuedTransactionList = function (reverse, limit) { return library.logic.transactionPool.getAll('unverified', {reverse: reverse, limit: limit}); }; /** - * Gets multisignature transactions based on limit. + * Gets multisignature transactions, with a limit option. * @implements {transactionPool.getAll} - * @param {boolean} reverse - * @param {number} limit - * @return {function} Calls transactionPool.getQueuedTransactionList + * @param {boolean} reverse - Reverse order of results. + * @param {number} limit - Limit applied to results. + * @return {transaction[]} Calls transactionPool.getQueuedTransactionList */ Transactions.prototype.getMultisignatureTransactionList = function (reverse, limit) { return library.logic.transactionPool.getAll('pending', {reverse: reverse, limit: limit}); }; /** - * Gets ready, pending and unverified transactions based on limit and reverse option. + * Gets ready, pending and unverified transactions, with limit and reverse options. * @implements {transactionPool.getMergedTransactionList} - * @param {boolean} reverse - * @param {number} limit - * @return {function} ready + pending + unverified + * @param {boolean} reverse - Reverse order of results. + * @param {number} limit - Limit applied to results. + * @return {transaction[]} Calls transactionPool.getMergedTransactionList */ Transactions.prototype.getMergedTransactionList = function (reverse, limit) { return library.logic.transactionPool.getMergedTransactionList(reverse, limit); }; /** - * Removes transaction from unconfirmed, queued and multisignature. + * Removes an unconfirmed transaction from the pool. * @implements {transactionPool.delete} - * @param {string} id - * @return {function} Calls transactionPool.removeUnconfirmedTransaction + * @param {string} id - Transaction id. + * @return {boolean} Calls transactionPool.delete */ Transactions.prototype.removeUnconfirmedTransaction = function (id) { return library.logic.transactionPool.delete(id); }; /** - * Removes transactions from pool lists if they are present and rechecks pool balance - * for sender. + * Removes transactions from the pool if they are present, and rechecks pool balance for sender. * @implements {transactionPool.sanitazeTransactions} - * @param {string} id - * @return {function} Calls transactionPool.sanitazeTransactions + * @param {string} id - Transaction id. + * @return {undefined} Calls transactionPool.sanitazeTransactions */ Transactions.prototype.sanitizeTransactionPool = function (transactions) { return library.logic.transactionPool.sanitizeTransactions(transactions); }; /** - * Adds a transaction to pool list if pass all validations. + * Adds a transaction to the pool if it passes all validations. * @implements {transactionPool.addFromPublic} - * @param {string} caller peer or public - * @param {transaction} transaction - * @param {boolean} broadcast + * @param {string} caller - Name of caller: 'peer' or 'public'. + * @param {object} transaction - Transaction object. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. */ Transactions.prototype.processUnconfirmedTransaction = function (caller, transaction, broadcast, cb) { @@ -405,16 +403,17 @@ Transactions.prototype.processUnconfirmedTransaction = function (caller, transac }; /** - * Adds a transaction to pool list. It will be processed later by processPool worker. + * Adds a transaction to pool list for later processing by processPool worker. * @implements {transactionPool.addFromPeer} - * @param {transaction} transactions - * @param {boolean} broadcast + * @param {array} transactions - Transactions received from peer. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. */ Transactions.prototype.processPeerTransactions = function (transactions, broadcast, cb) { return library.logic.transactionPool.addFromPeer(transactions, broadcast, cb); }; +// TODO: Remove this function /** * Gets unconfirmed transactions list and applies unconfirmed transactions. * @param {function} cb - Callback function. @@ -424,34 +423,34 @@ Transactions.prototype.applyUnconfirmedList = function (cb) { return __private.transactionPool.applyUnconfirmedList(cb); }; +// TODO: Remove this function /** * Applies unconfirmed list to unconfirmed Ids. - * @param {string[]} ids + * @param {string[]} ids - Transaction IDs. * @param {function} cb - Callback function. * @return {function} Calls transactionPool.applyUnconfirmedIds */ Transactions.prototype.applyUnconfirmedIds = function (ids, cb) { - // TODO: delete this function cb(); }; +// TODO: Remove this function /** * Undoes unconfirmed list from queue. * @param {function} cb - Callback function. * @return {function} Calls transactionPool.undoUnconfirmedList */ Transactions.prototype.undoUnconfirmedList = function (cb) { - // TODO: delete this function cb(); }; /** * Applies confirmed transaction. * @implements {logic.transaction.apply} - * @param {transaction} transaction - * @param {block} block - * @param {account} sender - * @param {function} cb - Callback function + * @param {transaction} transaction - Transaction being applied. + * @param {object} block - Block that transaction is being applied within. + * @param {object} sender - Sender account. + * @param {function} cb - Callback function. */ Transactions.prototype.apply = function (transaction, block, sender, cb) { library.logger.debug('Applying confirmed transaction', transaction.id); @@ -461,10 +460,10 @@ Transactions.prototype.apply = function (transaction, block, sender, cb) { /** * Undoes confirmed transaction. * @implements {logic.transaction.undo} - * @param {transaction} transaction - * @param {block} block - * @param {account} sender - * @param {function} cb - Callback function + * @param {transaction} transaction - Transaction being undone. + * @param {object} block - Block that transaction is being undone within. + * @param {object} sender - Sender account. + * @param {function} cb - Callback function. */ Transactions.prototype.undo = function (transaction, block, sender, cb) { library.logger.debug('Undoing confirmed transaction', transaction.id); @@ -475,10 +474,10 @@ Transactions.prototype.undo = function (transaction, block, sender, cb) { * Gets requester if requesterPublicKey and calls applyUnconfirmed. * @implements {modules.accounts.getAccount} * @implements {logic.transaction.applyUnconfirmed} - * @param {transaction} transaction - * @param {account} sender - * @param {function} cb - Callback function - * @return {setImmediateCallback} for errors + * @param {object} transaction - Transaction object. + * @param {object} sender - Sender account. + * @param {function} cb - Callback function. + * @return {setImmediateCallback} For error. */ Transactions.prototype.applyUnconfirmed = function (transaction, sender, cb) { library.logger.debug('Applying unconfirmed transaction', transaction.id); @@ -505,12 +504,12 @@ Transactions.prototype.applyUnconfirmed = function (transaction, sender, cb) { }; /** - * Validates account and Undoes unconfirmed transaction. + * Validates account and undoes unconfirmed transaction. * @implements {modules.accounts.getAccount} * @implements {logic.transaction.undoUnconfirmed} - * @param {transaction} transaction - * @param {function} cb - * @return {setImmediateCallback} For error + * @param {object} transaction - Transaction object. + * @param {function} cb - Callback function. + * @return {setImmediateCallback} For error. */ Transactions.prototype.undoUnconfirmed = function (transaction, cb) { library.logger.debug('Undoing unconfirmed transaction', transaction.id); @@ -523,10 +522,11 @@ Transactions.prototype.undoUnconfirmed = function (transaction, cb) { }); }; +// TODO: Remove this function /** - * Receives transactions - * @param {transaction[]} transactions - * @param {Object} broadcast + * Receives transactions. + * @param {array} transactions - Received transactions. + * @param {boolean} broadcast - Broadcast flag. * @param {function} cb - Callback function. * @return {function} Calls transactionPool.receiveTransactions */ @@ -574,7 +574,7 @@ Transactions.prototype.onBind = function (scope) { // Shared API /** - * @todo implement API comments with apidoc. + * @todo Implement API comments with apidoc. * @see {@link http://apidocjs.com/} */ Transactions.prototype.shared = { @@ -583,7 +583,7 @@ Transactions.prototype.shared = { function (waterCb) { // Query parameters which can have 1 or multiple values are parsed as strings when the have 1 value. We need to convert string into an array of length 1 _.each(req.body, function (value, key) { - // Dealing with parameters which must be array to array if they are string + // Dealing with parameters which must be array to array if they are string if (_.includes(['senderId', 'recipientId', 'senderPublicKey', 'recipientPublicKey'], key) && typeof value === 'string') { req.body[key] = [value]; } From 4f4c621c64695ded37d76c2a8702191e74086630 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 13:59:20 +0100 Subject: [PATCH 85/86] Review test/config.json --- test/config.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/config.json b/test/config.json index 421ae975b79..a29ab12c795 100644 --- a/test/config.json +++ b/test/config.json @@ -72,12 +72,12 @@ "relayLimit": 2 }, "transactions": { - "maxTxsPerQueue": 1000, - "pool": { - "storageLimit": 4000, - "processInterval": 5000, - "expiryInterval": 25000 - } + "maxTxsPerQueue": 1000, + "pool": { + "storageLimit": 4000, + "processInterval": 5000, + "expiryInterval": 25000 + } }, "forging": { "force": true, From 6e7b66f519c45fa0e1c0832f75638c471572d3c1 Mon Sep 17 00:00:00 2001 From: Oliver Beddows Date: Sun, 26 Nov 2017 14:00:04 +0100 Subject: [PATCH 86/86] Review test/unit/logic/transactions/pool.js --- test/unit/logic/transactions/pool.js | 361 ++++++++++++++------------- 1 file changed, 192 insertions(+), 169 deletions(-) diff --git a/test/unit/logic/transactions/pool.js b/test/unit/logic/transactions/pool.js index e8ff6da6054..af8f915b34d 100644 --- a/test/unit/logic/transactions/pool.js +++ b/test/unit/logic/transactions/pool.js @@ -53,67 +53,67 @@ describe('transactionPool', function () { ]; var transactions = [ - /* Type: 0 - Transmit funds.*/ + // Type: 0 - Transfer funds node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret), - /* Type: 1 - Register a second signature.*/ + // Type: 1 - Register a second signature node.lisk.signature.createSignature(testAccounts[0].secret, testAccounts[0].secret2), - /* Type: 2 - Register a delegate.*/ + // Type: 2 - Register a delegate node.lisk.delegate.createDelegate(testAccounts[3].secret, 'tpool_new_delegate'), - /* Type: 3 - Submit votes.*/ - node.lisk.vote.createVote(testAccounts[0].secret, + // Type: 3 - Place votes + node.lisk.vote.createVote(testAccounts[0].secret, ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), - /* Type: 4 - Multisignature registration.*/ + // Type: 4 - Multisignature registration [ - /* - Create normal multisignature, all accounts in database */ - createMultisignatureSigned (testAccounts[0].secret, null, - ['+' + testAccounts[1].account.publicKey, '+' + testAccounts[2].account.publicKey], + // Create normal multisignature, all accounts in database + createMultisignatureSigned (testAccounts[0].secret, null, + ['+' + testAccounts[1].account.publicKey, '+' + testAccounts[2].account.publicKey], [testAccounts[1].secret, testAccounts[2].secret], 1, 2), - /* - Create multisignature signed with signer account not register in database.*/ - createMultisignatureSigned (testAccounts[2].secret, null, - ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], + // Create multisignature signed with signer account not registered in database + createMultisignatureSigned (testAccounts[2].secret, null, + ['+6a23c387172fdf66654f27ccb451ceb4bed7507584c20ed5168f0e7a979f9c5e'], ['horse endless tag awkward pact reveal kiss april crash interest prefer lunch'], 1, 1), - /* - Create multisignature signed without enough signatures.*/ - createMultisignatureSigned (testAccounts[3].secret, null, + // Create 'non-ready' multisignature signed, with pending signatures + createMultisignatureSigned (testAccounts[3].secret, null, ['+' + testAccounts[2].account.publicKey,'+' + testAccounts[1].account.publicKey], [testAccounts[2].secret], 1, 2) ] ]; var invalidsTransactions = [ - /* Type: 0 - Transmit funds account without enough credit.*/ + // Type: 0 - Transfer from account without enough funds node.lisk.transaction.createTransaction(testAccounts[0].account.address, 4400000000000, testAccounts[1].secret), - /* Type: 1 - Register a second signature account without enough credit.*/ + // Type: 1 - Register a second signature account without enough funds node.lisk.signature.createSignature(testAccounts[1].secret, testAccounts[0].secret2), - /* Type: 2.*/ + // Type: 2 [ - /* - Register a delegate account without enough credit.*/ + // - Register a delegate account without enough funds node.lisk.delegate.createDelegate('genre spare shed home aim achieve second garbage army erode rubber baby', 'no_credit'), - /* - Register a delegate that already is delegate*/ + // - Register a delegate that is already a delegate node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username), - /* - Register a delegate account with existing username*/ + // - Register a delegate account with an existing username node.lisk.delegate.createDelegate(testAccounts[1].secret, 'genesis_101') ], - /* Type: 3.*/ + // Type: 3 [ - /* - Submit votes from an account without enough credit.*/ - node.lisk.vote.createVote(testAccounts[1].secret, + // - Place votes from an account without enough funds + node.lisk.vote.createVote(testAccounts[1].secret, ['+c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5']), - /* - Submit votes to an account that is not a delegate.*/ - node.lisk.vote.createVote(testAccounts[2].secret, + // - Place votes to an account that is not a delegate + node.lisk.vote.createVote(testAccounts[2].secret, ['+181414336a6642307feda947a697c36f299093de35bf0fb263ccdeccb497962c']) ], - /* Type: 4.*/ + // Type: 4 [ - /* - Create multisignature signed from an account without enough credit.*/ - createMultisignatureSigned (testAccounts[1].secret, null, + // - Create multisignature group signed from an account without enough funds + createMultisignatureSigned (testAccounts[1].secret, null, ['+' + testAccounts[3].account.publicKey], [testAccounts[3].secret], 1, 1), - /* - Create multisignature signed with invalid signature.*/ - createMultisignatureSigned (testAccounts[3].secret, null, + // - Create multisignature group signed with invalid signature + createMultisignatureSigned (testAccounts[3].secret, null, ['+' + testAccounts[2].account.publicKey], [testAccounts[1].secret], 1, 1) ] ]; var hackedTransactions = [ - /* Invalid signature */ + // Invalid signature { 'type': 2, 'amount': 0, @@ -140,8 +140,8 @@ describe('transactionPool', function () { var poolStorageTransactionsLimit; var dbSandbox; + // Reset state of spies function resetSpiesState () { - // Reset state of spies logger.info.reset(); logger.warn.reset(); logger.error.reset(); @@ -150,10 +150,13 @@ describe('transactionPool', function () { function createMultisignatureSigned (creatorSecret, creatorSecondSecret, keysgroup, signeersSecrets, min, lifetime) { var multisignatureTransaction = node.lisk.multisignature.createMultisignature(creatorSecret, creatorSecondSecret, keysgroup, min, lifetime); var signatures = []; + signeersSecrets.forEach(function (secret) { var sign = node.lisk.multisignature.signTransaction(multisignatureTransaction, secret); + signatures.push(sign); }); + multisignatureTransaction.signatures = signatures; return multisignatureTransaction; } @@ -161,20 +164,22 @@ describe('transactionPool', function () { function forge (cb) { function getNextForger (offset, cb) { offset = !offset ? 1 : offset; + var last_block = library.modules.blocks.lastBlock.get(); var slot = slots.getSlotNumber(last_block.timestamp); - // TODO: wait 0.9.10 backport to 1.0.0 to get delegate list - //library.modules.delegates.generateDelegateList(last_block.height, null, function (err, delegateList) { + + // TODO: Wait for 0.9.10 backport to 1.0.0 to get delegate list + // library.modules.delegates.generateDelegateList(last_block.height, null, function (err, delegateList) { library.modules.delegates.generateDelegateList(function (err, delegateList) { if (err) { return cb (err); } var nextForger = delegateList[(slot + offset) % slots.delegates]; return cb(nextForger); }); } - + var loadDelegates = library.rewiredModules.delegates.__get__('__private.loadDelegates'); - node.async.waterfall([ + node.async.waterfall([ loadDelegates, transactionPool.processPool, function (cb) { @@ -187,10 +192,12 @@ describe('transactionPool', function () { var last_block = library.modules.blocks.lastBlock.get(); var slot = slots.getSlotNumber(last_block.timestamp) + 1; var keypair = keypairs[delegate]; + node.debug(' Last block height: ' + last_block.height + ' Last block ID: ' + last_block.id + ' Last block timestamp: ' + last_block.timestamp + ' Next slot: ' + slot + ' Next delegate PK: ' + delegate + ' Next block timestamp: ' + slots.getSlotTime(slot)); library.modules.blocks.process.generateBlock(keypair, slots.getSlotTime(slot), function (err) { if (err) { return seriesCb(err); } last_block = library.modules.blocks.lastBlock.get(); + node.debug(' New last block height: ' + last_block.height + ' New last block ID: ' + last_block.id); return seriesCb(err); }); @@ -210,10 +217,13 @@ describe('transactionPool', function () { constants.unconfirmedTransactionTimeOut = 1; constants.signatureTransactionTimeOutMultiplier = 1; constants.secondsPerHour = 1; + poolStorageTransactionsLimit = modulesLoader.scope.config.transactions.pool.storageLimit = 6; + modulesLoader.scope.config.transactions.pool.processInterval = 60000000; modulesLoader.scope.config.transactions.pool.expiryInterval = 80000000; - // Wait for genesisBlock transaction being applied + + // Wait for genesis block to be applied node.initApplication(function (err, scope) { transactionPool = scope.logic.transactionPool; library = scope; @@ -232,11 +242,12 @@ describe('transactionPool', function () { node.appCleanup(done); }); - describe('setup database', function () { + describe('setting up database', function () { + var transaction; var totalDB; - it('should be ok when add account 1 transaction to unverified', function (done) { + it('should be ok when adding account 1 transaction to unverified', function (done) { transaction = node.lisk.transaction.createTransaction(testAccounts[0].account.address, testAccounts[0].account.balance, node.gAccount.password); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -245,7 +256,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add account 2 transaction to unverified', function (done) { + it('should be ok when adding account 2 transaction to unverified', function (done) { transaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, testAccounts[1].account.balance, node.gAccount.password); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -254,7 +265,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add account 3 transaction to unverified', function (done) { + it('should be ok when adding account 3 transaction to unverified', function (done) { transaction = node.lisk.transaction.createTransaction(testAccounts[2].account.address, testAccounts[2].account.balance, node.gAccount.password); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -263,7 +274,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add account 4 transaction to unverified', function (done) { + it('should be ok when adding account 4 transaction to unverified', function (done) { transaction = node.lisk.transaction.createTransaction(testAccounts[3].account.address, testAccounts[3].account.balance, node.gAccount.password); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -272,7 +283,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add delegate transaction to unverified', function (done) { + it('should be ok when adding delegate transaction to unverified', function (done) { transaction = node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -281,7 +292,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when get pool totals to initialize local counter', function (done) { + it('should be ok when getting pool totals to initialize local counter', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -293,7 +304,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when process transactions and create blocks', function (done) { + it('should be ok when processing transactions and creating blocks', function (done) { setTimeout(function () { forge(function (err, cbForge) { expect(err).to.be.null; @@ -304,7 +315,7 @@ describe('transactionPool', function () { }, 800); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -315,7 +326,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when add delegate transaction to unverified', function (done) { + it('should be ok when adding delegate transaction to unverified', function (done) { transaction = node.lisk.delegate.createDelegate(testAccounts[0].secret, testAccounts[0].account.username); transactionPool.addFromPeer(transaction, false, function (err, cbtransaction) { @@ -324,7 +335,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when process transactions and create blocks', function (done) { + it('should be ok when processing transactions and creating blocks', function (done) { setTimeout(function () { forge(function (err, cbForge) { expect(err).to.be.null; @@ -338,7 +349,7 @@ describe('transactionPool', function () { describe('process workers', function () { - it('should be ok when get pool totals to initialize local counter', function (done) { + it('should be ok when getting pool totals to initialize local counter', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -352,25 +363,25 @@ describe('transactionPool', function () { describe('processPool - no broadcast - addFromPeer', function () { - describe('Transaction type: 0 - Transmit funds', function () { + describe('transaction type: 0 - transferring funds', function () { var tmpTransactionInvalidId; - it('should be ok when add normal transaction to unverified', function (done) { + it('should be ok when adding normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with not enough LSK', function (done) { + it('should be ok when adding transaction to unverified with not enough LSK', function (done) { transactionPool.addFromPeer(invalidsTransactions[0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with invalid transaction id', function (done) { + it('should be ok when adding transaction to unverified with invalid transaction id', function (done) { tmpTransactionInvalidId = _.cloneDeep(invalidsTransactions[0]); tmpTransactionInvalidId.id = '01234567890123456789'; @@ -382,7 +393,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 3.00001'].join(' ')); @@ -391,21 +402,21 @@ describe('transactionPool', function () { }); }); - it('should fail when add same normal transaction to unverified', function (done) { + it('should fail when adding same normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[0], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[0].id); done(); }); }); - it('should fail when add same transaction with invalid id to unverified', function (done) { + it('should fail when adding same transaction with invalid id to unverified', function (done) { transactionPool.addFromPeer(tmpTransactionInvalidId, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + tmpTransactionInvalidId.id); done(); }); }); - it('should be ok when delete normal transaction from ready', function (done) { + it('should be ok when deleting normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[0].id); expect(deletedTransaction).to.equal('ready'); @@ -413,7 +424,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(poolTotals.invalid); @@ -421,7 +432,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -434,24 +445,25 @@ describe('transactionPool', function () { }); }); - describe('Transaction type: 1 - Register a second signature', function () { + describe('transaction type: 1 - registering a second signature', function () { + var invalidTransactionType; - it('should be ok when add normal transaction to unverified', function (done) { + it('should be ok when adding normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with not enough LSK', function (done) { + it('should be ok when adding transaction to unverified with not enough LSK', function (done) { transactionPool.addFromPeer(invalidsTransactions[1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should fail when add transaction to unverified with invalid transaction type', function (done) { + it('should fail when adding transaction to unverified with invalid transaction type', function (done) { invalidTransactionType = _.cloneDeep(invalidsTransactions[0]); invalidTransactionType.id = '12345678901234567890'; invalidTransactionType.type = 99; @@ -464,7 +476,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[1].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', testAccounts[1].account.address, 'balance: 0.00001'].join(' ')); @@ -473,21 +485,21 @@ describe('transactionPool', function () { }); }); - it('should fail when add same normal transaction to unverified', function (done) { + it('should fail when adding same normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[1].id); done(); }); }); - it('should fail when add same transaction with invalid transaction type to unverified', function (done) { + it('should fail when adding same transaction with invalid transaction type to unverified', function (done) { transactionPool.addFromPeer(invalidTransactionType, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidTransactionType.id); done(); }); }); - it('should be ok when delete normal transaction from ready', function (done) { + it('should be ok when deleting normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[1].id); expect(deletedTransaction).to.equal('ready'); @@ -495,7 +507,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(poolTotals.invalid); @@ -503,7 +515,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -516,38 +528,39 @@ describe('transactionPool', function () { }); }); - describe('Transaction type: 2 - Register a delegate', function () { + describe('transaction type: 2 - registering a delegate', function () { + var invalidSignature; - it('should be ok when add normal transaction to unverified', function (done) { + it('should be ok when adding normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with not enough LSK', function (done) { + it('should be ok when adding transaction to unverified with not enough LSK', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified that already is a delegate', function (done) { + it('should be ok when adding transaction to unverified that already is a delegate', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with same username', function (done) { + it('should be ok when adding transaction to unverified with same username', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with invalid signature', function (done) { + it('should be ok when adding transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { @@ -556,7 +569,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[2][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[2][0].senderId, 'balance: 0'].join(' ')); @@ -572,42 +585,42 @@ describe('transactionPool', function () { }); }); - it('should fail when add same normal transaction to unverified', function (done) { + it('should fail when adding same normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[2].id); done(); }); }); - it('should fail when add same transaction with registered delegate to unverified', function (done) { + it('should fail when adding same transaction with registered delegate to unverified', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); - it('should fail when add same transaction with registered delegate to unverified', function (done) { + it('should fail when adding same transaction with registered delegate to unverified', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][1].id); done(); }); }); - it('should fail when add same transaction with same username to unverified', function (done) { + it('should fail when adding same transaction with same username to unverified', function (done) { transactionPool.addFromPeer(invalidsTransactions[2][2], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[2][2].id); done(); }); }); - it('should fail when add same transaction with invalid signature to unverified', function (done) { + it('should fail when adding same transaction with invalid signature to unverified', function (done) { transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidSignature.id); done(); }); }); - it('should be ok when delete normal transaction from ready', function (done) { + it('should be ok when deleting normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[2].id); expect(deletedTransaction).to.equal('ready'); @@ -615,7 +628,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(poolTotals.invalid); @@ -623,7 +636,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -636,30 +649,30 @@ describe('transactionPool', function () { }); }); - describe('Transaction type: 3 - Submit votes', function () { + describe('transaction type: 3 - placing votes', function () { - it('should be ok when add normal transaction to unverified', function (done) { + it('should be ok when adding normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[3], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with not enough LSK', function (done) { + it('should be ok when adding transaction to unverified with not enough LSK', function (done) { transactionPool.addFromPeer(invalidsTransactions[3][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified that votes a non delegate', function (done) { + it('should be ok when adding transaction to unverified that votes for a non-delegate', function (done) { transactionPool.addFromPeer(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - - it('should be ok when process pool transactions', function (done) { + + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[3][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[3][0].senderId, 'balance: 0.00001'].join(' ')); @@ -671,21 +684,21 @@ describe('transactionPool', function () { }); }); - it('should fail when add same normal transaction to unverified', function (done) { + it('should fail when adding same normal transaction to unverified', function (done) { transactionPool.addFromPeer(transactions[3], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[3].id); done(); }); }); - it('should fail when add same transaction that votes a non delegate to unverified', function (done) { + it('should fail when adding same transaction that votes for a non-delegate to unverified', function (done) { transactionPool.addFromPeer(invalidsTransactions[3][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[3][1].id); done(); }); }); - it('should be ok when delete normal transaction from ready', function (done) { + it('should be ok when deleting normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[3].id); expect(deletedTransaction).to.equal('ready'); @@ -693,7 +706,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(poolTotals.invalid); @@ -701,7 +714,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -714,11 +727,12 @@ describe('transactionPool', function () { }); }); - describe('Transaction type: 4 - Multisignature registration', function () { + describe('transaction type: 4 - registering a multisignature group', function () { + var notEnoughSignatures; var completedSignatures; - it('should be ok when add normal transaction to unverified', function (done) { + it('should be ok when adding normal transaction to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { @@ -727,14 +741,14 @@ describe('transactionPool', function () { }); }); - it('should be ok when add transaction to unverified with not register signer in database', function (done) { + it('should be ok when adding transaction to unverified with unregistered signer in database', function (done) { transactionPool.addFromPeer(transactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified without enough signatures', function (done) { + it('should be ok when adding transaction to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { @@ -743,21 +757,21 @@ describe('transactionPool', function () { }); }); - it('should be ok when add transaction to unverified with not enough LSK', function (done) { + it('should be ok when adding transaction to unverified with not enough LSK', function (done) { transactionPool.addFromPeer(invalidsTransactions[4][0], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when add transaction to unverified with invalid signeer', function (done) { + it('should be ok when adding transaction to unverified with invalid signeer', function (done) { transactionPool.addFromPeer(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to check balance for account related with transaction: ' + invalidsTransactions[4][0].id); expect(logger.error.args[0][1]).to.equal(['Account does not have enough LSK:', invalidsTransactions[4][0].senderId, 'balance: 0.00001'].join(' ')); @@ -770,28 +784,28 @@ describe('transactionPool', function () { }); }); - it('should fail when add same normal transaction to unverified', function (done) { + it('should fail when adding same normal transaction to unverified', function (done) { transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + completedSignatures.id); done(); }); }); - it('should fail when add same transaction with unregister signer to unverified', function (done) { + it('should fail when adding same transaction with unregistered signer to unverified', function (done) { transactionPool.addFromPeer(transactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already in pool: ' + transactions[4][1].id); done(); }); }); - it('should fail when add same transaction without enough signatures to unverified', function (done) { + it('should fail when adding same transaction without enough signatures to unverified', function (done) { transactionPool.addFromPeer(invalidsTransactions[4][1], false, function (err, cbtransaction) { expect(err).to.equal('Transaction is already processed as invalid: ' + invalidsTransactions[4][1].id); done(); }); }); - it('should be ok when delete normal transaction from ready', function (done) { + it('should be ok when deleting normal transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(completedSignatures.id); expect(deletedTransaction).to.equal('ready'); @@ -799,7 +813,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when delete normal transaction without enough signatures to unverified', function (done) { + it('should be ok when deleting normal transaction without enough signatures to unverified', function (done) { var deletedTransaction = transactionPool.delete(transactions[4][1].id); expect(deletedTransaction).to.equal('ready'); @@ -807,7 +821,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(poolTotals.invalid); @@ -815,7 +829,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -827,16 +841,16 @@ describe('transactionPool', function () { done(); }); - describe('Sign multisignature', function () { + describe('signing multisignature', function () { - it('should fail when sign transaction with invalid signeer', function (done) { + it('should fail when signing transaction with invalid signer', function (done) { transactionPool.addSignature(transactions[4][2].id, testAccounts[0].secret, function (err, cbtransaction) { expect(err).to.equal('Permission to sign transaction denied'); done(); }); }); - it('should be ok when sign pending transaction', function (done) { + it('should be ok when signing pending transaction', function (done) { transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.be.undefined; expect(cbtransaction).to.be.undefined; @@ -844,14 +858,14 @@ describe('transactionPool', function () { }); }); - it('should fail when sign same pending transaction again', function (done) { + it('should fail when signing same pending transaction again', function (done) { transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.equal('Transaction already signed'); done(); }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args.length).to.equal(0); poolTotals.pending -= 1; @@ -860,14 +874,14 @@ describe('transactionPool', function () { }); }); - it('should fail when sign transaction that is not in the pool', function (done) { + it('should fail when signing transaction that is not in the pool', function (done) { transactionPool.addSignature(transactions[4][2].id, testAccounts[1].secret, function (err, cbtransaction) { expect(err).to.equal('Transaction not in pool'); done(); }); }); - it('should be ok when delete transaction from ready', function (done) { + it('should be ok when deleting transaction from ready', function (done) { var deletedTransaction = transactionPool.delete(transactions[4][2].id); expect(deletedTransaction).to.equal('ready'); @@ -875,7 +889,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -890,13 +904,14 @@ describe('transactionPool', function () { }); }); - describe('expireTransactions', function () { + describe('transaction expiry', function () { + var invalidSignature; var completedSignatures; var notEnoughSignatures; var normalTransaction; - it('should be ok when add transaction to unverified with invalid signature', function (done) { + it('should be ok when adding transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { @@ -905,7 +920,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add normal transaction type 4 to unverified', function (done) { + it('should be ok when adding normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { @@ -914,7 +929,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { + it('should be ok when adding transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { @@ -923,18 +938,18 @@ describe('transactionPool', function () { }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(logger.error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; - poolTotals.ready += 1; + poolTotals.ready += 1; poolTotals.pending += 1; done(); }); }); - it('should be ok when add normal transaction type 2 to unverified', function (done) { + it('should be ok when adding normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); transactionPool.addFromPeer(normalTransaction, false, function (err, cbtransaction) { @@ -944,7 +959,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -956,7 +971,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get transaction from unverified list', function (done) { + it('should be ok when getting transaction from unverified list', function (done) { var transaction = transactionPool.get(normalTransaction.id); expect(transaction.transaction).to.deep.equal(normalTransaction); @@ -965,7 +980,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get transaction from pending list', function (done) { + it('should be ok when getting transaction from pending list', function (done) { var transaction = transactionPool.get(notEnoughSignatures.id); expect(transaction.transaction).to.deep.equal(notEnoughSignatures); @@ -974,7 +989,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get transaction from ready list', function (done) { + it('should be ok when getting transaction from ready list', function (done) { var transaction = transactionPool.get(completedSignatures.id); expect(transaction.transaction).to.deep.equal(completedSignatures); @@ -983,7 +998,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when exprire transactions', function (done) { + it('should be ok when expriring transactions', function (done) { setTimeout(function () { transactionPool.expireTransactions(function (err, cbprPool) { expect(logger.info.args.length).to.equal(3); @@ -999,7 +1014,7 @@ describe('transactionPool', function () { }); - it('should be ok when reset invalid transactions list', function (done) { + it('should be ok when resetting invalid transactions list', function (done) { var invalidTransactions = transactionPool.resetInvalidTransactions(); expect(invalidTransactions).to.equal(1); @@ -1007,7 +1022,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get pool totals', function (done) { + it('should be ok when getting pool totals', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -1022,14 +1037,15 @@ describe('transactionPool', function () { }); describe('getters', function () { + var invalidSignature; var completedSignatures; var notEnoughSignatures; var normalTransaction; - describe('load transactions to pool', function () { + describe('adding transactions to pool', function () { - it('should be ok when add transaction to unverified with invalid signature', function (done) { + it('should be ok when adding transaction to unverified with invalid signature', function (done) { invalidSignature = _.cloneDeep(hackedTransactions[0]); transactionPool.addFromPeer(invalidSignature, false, function (err, cbtransaction) { @@ -1038,7 +1054,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add normal transaction type 4 to unverified', function (done) { + it('should be ok when adding normal transaction type 4 to unverified', function (done) { completedSignatures = _.cloneDeep(transactions[4][0]); transactionPool.addFromPeer(completedSignatures, false, function (err, cbtransaction) { @@ -1047,7 +1063,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add transaction type 4 to unverified without enough signatures', function (done) { + it('should be ok when adding transaction type 4 to unverified without enough signatures', function (done) { notEnoughSignatures = _.cloneDeep(transactions[4][2]); transactionPool.addFromPeer(notEnoughSignatures, false, function (err, cbtransaction) { @@ -1056,18 +1072,18 @@ describe('transactionPool', function () { }); }); - it('should be ok when process pool transactions', function (done) { + it('should be ok when processing pool transactions', function (done) { transactionPool.processPool(function (err, cbprPool) { expect(logger.error.args[0][0]).to.equal('Failed to process unverified transaction: ' + invalidSignature.id); expect(logger.error.args[0][1]).to.equal('Failed to verify signature'); poolTotals.invalid += 1; - poolTotals.ready += 1; + poolTotals.ready += 1; poolTotals.pending += 1; done(); }); }); - it('should be ok when add normal transaction type 2 to unverified', function (done) { + it('should be ok when adding normal transaction type 2 to unverified', function (done) { normalTransaction = _.cloneDeep(transactions[2]); transactionPool.addFromPeer(normalTransaction, false, function (err, cbtransaction) { @@ -1077,7 +1093,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when add valid transaction type 3 to unverified', function (done) { + it('should be ok when adding valid transaction type 3 to unverified', function (done) { var normalTransactionT3 = _.cloneDeep(transactions[3]); transactionPool.addFromPeer(normalTransactionT3, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; @@ -1087,7 +1103,7 @@ describe('transactionPool', function () { }); }); - describe('get transaction by id', function () { + describe('getting a transaction by id', function () { it('should be ok when transaction is in unverified list', function (done) { var transaction = transactionPool.get(normalTransaction.id); @@ -1122,46 +1138,46 @@ describe('transactionPool', function () { }); }); - describe('getAll', function () { + describe('getting all transactions', function () { describe('by pool list', function () { - it('should be ok when check pool list unverified', function (done) { + it('should be ok when checking pool list unverified', function (done) { var transactions = transactionPool.getAll('unverified', {limit: null}); expect(Object.keys(transactions).length).to.equal(poolTotals.unverified); done(); }); - it('should be ok when check pool list unverified with limit', function (done) { + it('should be ok when checking pool list unverified with limit', function (done) { var transactions = transactionPool.getAll('unverified', { limit: 1 }); expect(Object.keys(transactions).length).to.equal(1); done(); }); - it('should be ok when check pool list pending', function (done) { + it('should be ok when checking pool list pending', function (done) { var transactions = transactionPool.getAll('pending', {limit: null}); expect(Object.keys(transactions).length).to.equal(1); done(); }); - it('should be ok when check pool list pending with limit', function (done) { + it('should be ok when checking pool list pending with limit', function (done) { var transactions = transactionPool.getAll('pending', {limit: 1}); expect(Object.keys(transactions).length).to.equal(1); done(); }); - it('should be ok when check pool list ready', function (done) { + it('should be ok when checking pool list ready', function (done) { var transactions = transactionPool.getAll('ready', {limit: null}); expect(Object.keys(transactions).length).to.equal(poolTotals.ready); done(); }); - it('should be ok when check pool list ready with limit', function (done) { + it('should be ok when checking pool list ready with limit', function (done) { var transactions = transactionPool.getAll('ready', {limit: 1}); expect(Object.keys(transactions).length).to.equal(1); @@ -1205,7 +1221,7 @@ describe('transactionPool', function () { done(); }); - // TODO: turn on this test after move to new db schema + // TODO: Enable this test after moving to new db schema it.skip('should be ok when recipient publicKey is valid', function (done) { var transactions = transactionPool.getAll('recipient_pk', {publicKey: 'c76a0e680e83f47cf07c0f46b410f3b97e424171057a0f8f0f420c613da2f7b5'}); @@ -1220,10 +1236,11 @@ describe('transactionPool', function () { describe('unverified', function () { - describe('method add', function () { + describe('add', function () { - it('should be ok when add transactions to fill pool storage', function (done) { + it('should be ok when adding transactions to fill pool storage', function (done) { var transactions = []; + invalidsTransactions.forEach(function (e) { if (Array.isArray(e)) { transactions = transactions.concat(e); @@ -1231,6 +1248,7 @@ describe('transactionPool', function () { transactions.push(e); } }); + transactionPool.addFromPeer(transactions, false, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; expect(err).to.equal('Transaction pool is full'); @@ -1246,8 +1264,9 @@ describe('transactionPool', function () { done(); }); - it('should fail when add transaction and pool storage is full', function (done) { + it('should fail when adding transaction and pool storage is full', function (done) { var extraTransaction = node.lisk.transaction.createTransaction(testAccounts[1].account.address, 300000000, testAccounts[0].secret); + transactionPool.addFromPeer(extraTransaction, false, function (err, cbtransaction) { expect(err).to.equal('Transaction pool is full'); done(); @@ -1255,16 +1274,16 @@ describe('transactionPool', function () { }); }); - describe('method delete', function () { + describe('delete', function () { - it('should be ok when delete a transaction from unverified', function (done) { + it('should be ok when deleting a transaction from unverified', function (done) { var deleteTransaction = transactionPool.delete(invalidsTransactions[0].id); expect(deleteTransaction).to.equal('unverified'); done(); }); - it('should be ok when check unverified value decreased in 1', function (done) { + it('should be ok when checking unverified value has decreased by 1', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -1273,7 +1292,7 @@ describe('transactionPool', function () { done(); }); - it('should fail when delete transaction that is not in pool', function (done) { + it('should fail when deleting transaction that is not in pool', function (done) { var deleteTransaction = transactionPool.delete(transactions[0].id); expect(deleteTransaction).to.be.undefined; @@ -1283,8 +1302,11 @@ describe('transactionPool', function () { }); describe('ready', function () { - describe('method addReady/getReady', function () { + + describe('addReady/getReady', function () { + var allTransactions = []; + transactions.forEach(function (e) { if (Array.isArray(e)) { allTransactions = allTransactions.concat(e); @@ -1294,7 +1316,7 @@ describe('transactionPool', function () { }); allTransactions.pop(); - it('should be ok when add transactions to ready', function (done) { + it('should be ok when adding transactions to ready', function (done) { transactionPool.addReady(allTransactions, function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; poolTotals.ready = allTransactions.length; @@ -1302,7 +1324,7 @@ describe('transactionPool', function () { }); }); - it('should be ok when get transactions from ready', function (done) { + it('should be ok when getting transactions from ready', function (done) { var readyTransactions = transactionPool.getReady(); expect(readyTransactions[0].fee).to.be.at.least(readyTransactions[1].fee); @@ -1313,14 +1335,14 @@ describe('transactionPool', function () { done(); }); - it('should be ok when add type 2 transaction again to ready', function (done) { + it('should be ok when adding type 2 transaction again to ready', function (done) { transactionPool.addReady([allTransactions[2]], function (err, cbtransaction) { expect(cbtransaction).to.be.undefined; done(); }); }); - it('should be ok when get transactions from ready', function (done) { + it('should be ok when getting transactions from ready', function (done) { var readyTransactions = transactionPool.getReady(); expect(readyTransactions[0].receivedAt).to.not.equal(readyTransactions[1].receivedAt); @@ -1330,7 +1352,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when get transactions from ready with limit', function (done) { + it('should be ok when getting transactions from ready with limit', function (done) { var readyTransactions = transactionPool.getReady(2); expect(readyTransactions.length).to.equal(2); @@ -1338,7 +1360,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when delete transaction from ready', function (done) { + it('should be ok when deleting transaction from ready', function (done) { var deleteTransaction = transactionPool.delete(transactions[0].id); expect(deleteTransaction).to.equal('ready'); @@ -1346,7 +1368,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when check ready value decreased in 1', function (done) { + it('should be ok when checking ready value has decreased by 1', function (done) { var totals = transactionPool.getUsage(); expect(totals).to.be.an('object'); @@ -1356,10 +1378,11 @@ describe('transactionPool', function () { }); }); - describe('broadcast transactions', function () { + describe('broadcasting transactions', function () { + var broadcastTransaction; - it('should be ok when serialize transaction', function (done) { + it('should be ok when serializing transaction', function (done) { broadcastTransaction = bson.serialize(transactions[0]); expect(broadcastTransaction).that.is.an('Uint8Array'); @@ -1374,7 +1397,7 @@ describe('transactionPool', function () { done(); }); - it('should be ok when deserialize transaction', function (done) { + it('should be ok when deserializing transaction', function (done) { broadcastTransaction = bson.deserialize(broadcastTransaction); expect(broadcastTransaction).to.deep.equal(transactions[0]); @@ -1382,16 +1405,16 @@ describe('transactionPool', function () { }); }); - describe('checkBalance', function () { + describe('checking balances', function () { - it('should be ok when checked account balance with enough LSK for transaction', function (done) { + it('should be ok when checking account balance with enough LSK for transaction', function (done) { transactionPool.checkBalance(transactions[0], {address: transactions[0].senderId}, function (err, cbBalance) { expect(cbBalance).to.equal('balance: 4999969'); done(); }); }); - it('should fail when checked account balance with not enough LSK for transaction', function (done) { + it('should fail when checking account balance with not enough LSK for transaction', function (done) { transactionPool.checkBalance(invalidsTransactions[0], { address: invalidsTransactions[0].senderId }, function (err, cbBalance) { expect(err).to.equal('Account does not have enough LSK: 2896019180726908125L balance: 0.00001'); done();