Improved block sync speed
-A number of functions have been rewritten to be more optimized and faster: calculate_total, is_unique, convert_to_satoshi, get_input_addresses, processVoutAddresses, prepare_vout, prepare_vin -Txes are now written to database via bulk writes which helps improve the sync speed and also controls memory usage with batching to write data once a certain threshold is reached -update_address function changed to update_addresses since it now bulk writes the addresses in batches to improve sync speed and also controls memory usage with batching to write data once a certain threshold is reached -The syncLoop function has been completely removed from the project and replaced with async library loops or even normal "for" loops in some cases which greatly improves sync speeds over large batches of data -Fixed an issue with the flattened count of txes that is saved to the coinstats collection which could save incorrectly when using more than 1 thread -Fixed an issue with the block sync which caused an unwanted delay when syncing less blocks than the amount of threads used to sync the data -Fixed an issue with vout data processing that could sometimes populate data out of order -Added a new sync.batch_size setting used to determine how many records (txes, addresses, addresstxes) should be saved in a single database transaction -Added a new wait_for_bulk_database_save setting used to increase the block sync speed at the cost of not returning any error msgs for data that failed to save -get_input_addresses function no longer returns in the exports section of the explorer.js file since it is only referenced in that file -Updated explorerspec tests to use the newest function changes for any tests that needed to be updated Special thanks to Karzo from Pepecoin for help with the bulkwrite code changes!
This commit is contained in:
+92
-110
@@ -1,19 +1,20 @@
|
||||
var mongoose = require('mongoose'),
|
||||
Stats = require('../models/stats'),
|
||||
Markets = require('../models/markets'),
|
||||
Masternode = require('../models/masternode'),
|
||||
Address = require('../models/address'),
|
||||
AddressTx = require('../models/addresstx'),
|
||||
Tx = require('../models/tx'),
|
||||
Orphans = require('../models/orphans'),
|
||||
Richlist = require('../models/richlist'),
|
||||
Peers = require('../models/peers'),
|
||||
Heavy = require('../models/heavy'),
|
||||
NetworkHistory = require('../models/networkhistory'),
|
||||
ClaimAddress = require('../models/claimaddress'),
|
||||
lib = require('./explorer'),
|
||||
settings = require('./settings'),
|
||||
fs = require('fs');
|
||||
const mongoose = require('mongoose');
|
||||
const Stats = require('../models/stats');
|
||||
const Markets = require('../models/markets');
|
||||
const Masternode = require('../models/masternode');
|
||||
const Address = require('../models/address');
|
||||
const AddressTx = require('../models/addresstx');
|
||||
const Tx = require('../models/tx');
|
||||
const Orphans = require('../models/orphans');
|
||||
const Richlist = require('../models/richlist');
|
||||
const Peers = require('../models/peers');
|
||||
const Heavy = require('../models/heavy');
|
||||
const NetworkHistory = require('../models/networkhistory');
|
||||
const ClaimAddress = require('../models/claimaddress');
|
||||
const lib = require('./explorer');
|
||||
const settings = require('./settings');
|
||||
const fs = require('fs');
|
||||
const async = require('async');
|
||||
|
||||
function find_address(hash, caseSensitive, cb) {
|
||||
if (caseSensitive) {
|
||||
@@ -250,24 +251,22 @@ function remove_inactive_markets(installed_markets, cb) {
|
||||
// check if the database has any markets installed
|
||||
if (db_markets != null && db_markets.length > 0) {
|
||||
// loop through the list of markets in the database
|
||||
lib.syncLoop(db_markets.length, function(market_loop) {
|
||||
let m = market_loop.iteration();
|
||||
|
||||
async.eachSeries(db_markets, function(current_market, market_loop) {
|
||||
// check if this market is installed
|
||||
if (installed_markets.findIndex(x => x.market.toUpperCase() == db_markets[m].market.toUpperCase() && x.coin_symbol.toUpperCase() == db_markets[m].coin_symbol.toUpperCase() && x.pair_symbol.toUpperCase() == db_markets[m].pair_symbol.toUpperCase()) == -1) {
|
||||
if (installed_markets.findIndex(x => x.market.toUpperCase() == current_market.market.toUpperCase() && x.coin_symbol.toUpperCase() == current_market.coin_symbol.toUpperCase() && x.pair_symbol.toUpperCase() == current_market.pair_symbol.toUpperCase()) == -1) {
|
||||
// remove this market from the database because it is not installed or active
|
||||
Markets.deleteOne({market: db_markets[m].market, coin_symbol: db_markets[m].coin_symbol, pair_symbol: db_markets[m].pair_symbol}).then(() => {
|
||||
Markets.deleteOne({market: current_market.market, coin_symbol: current_market.coin_symbol, pair_symbol: current_market.pair_symbol}).then(() => {
|
||||
// move to the next market record
|
||||
market_loop.next();
|
||||
market_loop();
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
|
||||
// move to the next market record
|
||||
market_loop.next();
|
||||
market_loop();
|
||||
});
|
||||
} else {
|
||||
// move to the next market record
|
||||
market_loop.next();
|
||||
market_loop();
|
||||
}
|
||||
}, function() {
|
||||
// finished removing inactive markets
|
||||
@@ -299,35 +298,30 @@ function init_heavy(cb) {
|
||||
function init_claimaddress(coin, cb) {
|
||||
// first, get the stats data
|
||||
Stats.findOne({coin: coin}).then((stats) => {
|
||||
var newer_claim_address = false;
|
||||
let newer_claim_address = false;
|
||||
|
||||
// check if stats were found
|
||||
if (stats) {
|
||||
// check if the claim address data was already moved to the new collection
|
||||
if (stats.newer_claim_address != null && stats.newer_claim_address == true)
|
||||
newer_claim_address = true;
|
||||
}
|
||||
// check if stats were found and the claim address data was already moved to the new collection
|
||||
if (stats && stats.newer_claim_address != null && stats.newer_claim_address == true)
|
||||
newer_claim_address = true;
|
||||
|
||||
// check if the claim address data should be moved to a new collection
|
||||
if (!newer_claim_address) {
|
||||
// find all addresses with a custom claim address name
|
||||
Address.find({$and: [{"name": {$ne: ""}}, {"name": {$ne: null}}]}).exec().then((addresses) => {
|
||||
Address.find({$and: [{'name': {$ne: ''}}, {'name': {$ne: null}}]}).exec().then((addresses) => {
|
||||
// loop through the claimed addresses
|
||||
lib.syncLoop(addresses.length, function(address_loop) {
|
||||
var a = address_loop.iteration();
|
||||
|
||||
async.eachSeries(addresses, function(current_address, address_loop) {
|
||||
// create a new claimaddress record
|
||||
var claim_address = new ClaimAddress({
|
||||
a_id: addresses[a].a_id,
|
||||
claim_name: addresses[a].name
|
||||
const claim_address = new ClaimAddress({
|
||||
a_id: current_address.a_id,
|
||||
claim_name: current_address.name
|
||||
});
|
||||
|
||||
// add new claim address to collection
|
||||
claim_address.save().then(() => {
|
||||
address_loop.next();
|
||||
address_loop();
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
address_loop.next();
|
||||
address_loop();
|
||||
});
|
||||
}, function() {
|
||||
// finished moving all claimed address data to the new collection
|
||||
@@ -864,17 +858,17 @@ module.exports = {
|
||||
},
|
||||
|
||||
get_txs: function(block, cb) {
|
||||
var txs = [];
|
||||
let txs = [];
|
||||
|
||||
lib.syncLoop(block.tx.length, function (loop) {
|
||||
var i = loop.iteration();
|
||||
|
||||
find_tx(block.tx[i], function(tx) {
|
||||
async.eachSeries(block.tx, function(current_tx, loop) {
|
||||
find_tx(current_tx[i], function(tx) {
|
||||
if (tx) {
|
||||
// add tx to the list
|
||||
txs.push(tx);
|
||||
loop.next();
|
||||
} else
|
||||
loop.next();
|
||||
}
|
||||
|
||||
// move to next tx
|
||||
loop();
|
||||
});
|
||||
}, function() {
|
||||
return cb(txs);
|
||||
@@ -951,14 +945,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
get_address_txs_ajax: function(hash, start, length, cb) {
|
||||
var totalCount = 0;
|
||||
|
||||
AddressTx.find({a_id: hash}).countDocuments().then((count) => {
|
||||
totalCount = count;
|
||||
|
||||
AddressTx.find({a_id: hash}).countDocuments().then((totalCount) => {
|
||||
AddressTx.aggregate([
|
||||
{ $match: { a_id: hash } },
|
||||
{ $sort: {blockindex: -1} },
|
||||
{ $sort: { blockindex: -1 } },
|
||||
{ $skip: Number(start) },
|
||||
{
|
||||
$group: {
|
||||
@@ -972,29 +962,27 @@ module.exports = {
|
||||
balance: '$balance'
|
||||
}
|
||||
},
|
||||
{ $sort: {blockindex: -1} }
|
||||
{ $sort: { blockindex: -1 } }
|
||||
]).then((balance_sum) => {
|
||||
AddressTx.find({a_id: hash}).sort({blockindex: -1}).skip(Number(start)).limit(Number(length)).exec().then((address_tx) => {
|
||||
var txs = [];
|
||||
var count = address_tx.length;
|
||||
var running_balance = balance_sum.length > 0 ? balance_sum[0].balance : 0;
|
||||
var txs = [];
|
||||
let txs = [];
|
||||
let running_balance = (balance_sum.length > 0 ? balance_sum[0].balance : 0);
|
||||
|
||||
lib.syncLoop(count, function (loop) {
|
||||
var i = loop.iteration();
|
||||
|
||||
find_tx(address_tx[i].txid, function (tx) {
|
||||
if (tx && !txs.includes(tx)) {
|
||||
async.eachSeries(address_tx, function(current_addresstx, loop) {
|
||||
find_tx(current_addresstx.txid, function(tx) {
|
||||
if (tx) {
|
||||
// set the balance for this tx
|
||||
tx.balance = running_balance;
|
||||
txs.push(tx);
|
||||
loop.next();
|
||||
} else if (!txs.includes(tx)) {
|
||||
txs.push("1. Not found");
|
||||
loop.next();
|
||||
} else
|
||||
loop.next();
|
||||
|
||||
running_balance = running_balance - address_tx[i].amount;
|
||||
// add tx to list of txes
|
||||
txs.push(tx);
|
||||
|
||||
// subtract from the running balance
|
||||
running_balance -= current_addresstx.amount;
|
||||
}
|
||||
|
||||
// move to next address tx
|
||||
loop();
|
||||
});
|
||||
}, function () {
|
||||
return cb(txs, totalCount);
|
||||
@@ -1133,7 +1121,7 @@ module.exports = {
|
||||
},
|
||||
|
||||
get_distribution: function(richlist, stats, cb) {
|
||||
var distribution = {
|
||||
const distribution = {
|
||||
supply: stats.supply,
|
||||
t_1_25: {percent: 0, total: 0 },
|
||||
t_26_50: {percent: 0, total: 0 },
|
||||
@@ -1142,32 +1130,30 @@ module.exports = {
|
||||
t_101plus: {percent: 0, total: 0 }
|
||||
};
|
||||
|
||||
lib.syncLoop(richlist.balance.length, function (loop) {
|
||||
var i = loop.iteration();
|
||||
var count = i + 1;
|
||||
var percentage = ((richlist.balance[i].balance / 100000000) / stats.supply) * 100;
|
||||
async.timesSeries(richlist.balance.length, function(i, loop) {
|
||||
const percentage = ((richlist.balance[i].balance / 100000000) / stats.supply) * 100;
|
||||
|
||||
if (count <= 25 ) {
|
||||
if ((i + 1) <= 25) {
|
||||
distribution.t_1_25.percent = distribution.t_1_25.percent + percentage;
|
||||
distribution.t_1_25.total = distribution.t_1_25.total + (richlist.balance[i].balance / 100000000);
|
||||
}
|
||||
|
||||
if (count <= 50 && count > 25) {
|
||||
if ((i + 1) <= 50 && (i + 1) > 25) {
|
||||
distribution.t_26_50.percent = distribution.t_26_50.percent + percentage;
|
||||
distribution.t_26_50.total = distribution.t_26_50.total + (richlist.balance[i].balance / 100000000);
|
||||
}
|
||||
|
||||
if (count <= 75 && count > 50) {
|
||||
if ((i + 1) <= 75 && (i + 1) > 50) {
|
||||
distribution.t_51_75.percent = distribution.t_51_75.percent + percentage;
|
||||
distribution.t_51_75.total = distribution.t_51_75.total + (richlist.balance[i].balance / 100000000);
|
||||
}
|
||||
|
||||
if (count <= 100 && count > 75) {
|
||||
if ((i + 1) <= 100 && (i + 1) > 75) {
|
||||
distribution.t_76_100.percent = distribution.t_76_100.percent + percentage;
|
||||
distribution.t_76_100.total = distribution.t_76_100.total + (richlist.balance[i].balance / 100000000);
|
||||
}
|
||||
|
||||
loop.next();
|
||||
loop();
|
||||
}, function() {
|
||||
distribution.t_101plus.percent = parseFloat(100 - distribution.t_76_100.percent - distribution.t_51_75.percent - distribution.t_26_50.percent - distribution.t_1_25.percent - (settings.richlist_page.burned_coins.include_burned_coins_in_distribution == true && richlist.burned > 0 ? ((richlist.burned / 100000000) / stats.supply) * 100 : 0)).toFixed(2);
|
||||
distribution.t_101plus.total = parseFloat(distribution.supply - distribution.t_76_100.total - distribution.t_51_75.total - distribution.t_26_50.total - distribution.t_1_25.total - (settings.richlist_page.burned_coins.include_burned_coins_in_distribution == true && richlist.burned > 0 ? (richlist.burned / 100000000) : 0)).toFixed(8);
|
||||
@@ -1187,23 +1173,21 @@ module.exports = {
|
||||
// updates heavycoin stats
|
||||
// height: current block height, count: amount of votes to store
|
||||
update_heavy: function(coin, height, count, cb) {
|
||||
var newVotes = [];
|
||||
lib.get_maxmoney(function(maxmoney) {
|
||||
lib.get_maxvote(function(maxvote) {
|
||||
lib.get_vote(function(vote) {
|
||||
lib.get_phase(function(phase) {
|
||||
lib.get_reward(function(reward) {
|
||||
module.exports.get_stats(settings.coin.name, function(stats) {
|
||||
lib.get_estnext(function(estnext) {
|
||||
lib.get_nextin(function(nextin) {
|
||||
let newVotes = [];
|
||||
|
||||
lib.get_maxmoney( function (maxmoney) {
|
||||
lib.get_maxvote( function (maxvote) {
|
||||
lib.get_vote( function (vote) {
|
||||
lib.get_phase( function (phase) {
|
||||
lib.get_reward( function (reward) {
|
||||
module.exports.get_stats(settings.coin.name, function (stats) {
|
||||
lib.get_estnext( function (estnext) {
|
||||
lib.get_nextin( function (nextin) {
|
||||
lib.syncLoop(count, function (loop) {
|
||||
var i = loop.iteration();
|
||||
|
||||
lib.get_blockhash(height - i, function (hash) {
|
||||
lib.get_block(hash, function (block) {
|
||||
async.timesSeries(count, function(i, loop) {
|
||||
lib.get_blockhash(height - i, function(hash) {
|
||||
lib.get_block(hash, function(block) {
|
||||
newVotes.push({ count: height - i, reward: block.reward, vote: (block && block.vote ? block.vote : 0) });
|
||||
loop.next();
|
||||
loop();
|
||||
});
|
||||
});
|
||||
}, function() {
|
||||
@@ -1219,7 +1203,7 @@ module.exports = {
|
||||
votes: newVotes
|
||||
}).then(() => {
|
||||
// update reward_last_updated value
|
||||
module.exports.update_last_updated_stats(settings.coin.name, { reward_last_updated: Math.floor(new Date() / 1000) }, function (new_cb) {
|
||||
module.exports.update_last_updated_stats(settings.coin.name, { reward_last_updated: Math.floor(new Date() / 1000) }, function (update_success) {
|
||||
console.log('Heavycoin update complete');
|
||||
return cb();
|
||||
});
|
||||
@@ -1830,10 +1814,10 @@ module.exports = {
|
||||
},
|
||||
|
||||
populate_claim_address_names: function(tx, cb) {
|
||||
var addresses = [];
|
||||
const addresses = [];
|
||||
|
||||
// loop through vin addresses
|
||||
tx.vin.forEach(function (vin) {
|
||||
tx.vin.forEach(function(vin) {
|
||||
// check if this address already exists
|
||||
if (addresses.indexOf(vin.addresses) == -1) {
|
||||
// add address to array
|
||||
@@ -1842,7 +1826,7 @@ module.exports = {
|
||||
});
|
||||
|
||||
// loop through vout addresses
|
||||
tx.vout.forEach(function (vout) {
|
||||
tx.vout.forEach(function(vout) {
|
||||
// check if this address already exists
|
||||
if (addresses.indexOf(vout.addresses) == -1) {
|
||||
// add address to array
|
||||
@@ -1851,31 +1835,29 @@ module.exports = {
|
||||
});
|
||||
|
||||
// loop through address array
|
||||
lib.syncLoop(addresses.length, function(loop) {
|
||||
var a = loop.iteration();
|
||||
|
||||
module.exports.get_claim_name(addresses[a], function(claim_name) {
|
||||
async.eachSeries(addresses, function(current_address, loop) {
|
||||
module.exports.get_claim_name(current_address, function(claim_name) {
|
||||
if (claim_name != null && claim_name != '') {
|
||||
// look for address in vin
|
||||
for (v = 0; v < tx.vin.length; v++) {
|
||||
for (let v = 0; v < tx.vin.length; v++) {
|
||||
// check if this is the correct address
|
||||
if (tx.vin[v].addresses == addresses[a]) {
|
||||
if (tx.vin[v].addresses == current_address) {
|
||||
// add claim name to array
|
||||
tx.vin[v]['claim_name'] = claim_name;
|
||||
}
|
||||
}
|
||||
|
||||
// look for address in vout
|
||||
for (v = 0; v < tx.vout.length; v++) {
|
||||
for (let v = 0; v < tx.vout.length; v++) {
|
||||
// check if this is the correct address
|
||||
if (tx.vout[v].addresses == addresses[a]) {
|
||||
if (tx.vout[v].addresses == current_address) {
|
||||
// add claim name to array
|
||||
tx.vout[v]['claim_name'] = claim_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loop.next();
|
||||
loop();
|
||||
});
|
||||
}, function() {
|
||||
// return modified tx object
|
||||
|
||||
Reference in New Issue
Block a user