Compare commits
89 Commits
buffer-fix
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8121a2ba96 | ||
|
|
31344d770e | ||
|
|
96677310c2 | ||
|
|
e180672583 | ||
|
|
158d5aefc2 | ||
|
|
e7248320a6 | ||
|
|
60289a644b | ||
|
|
d42e569008 | ||
|
|
6beb2ecd06 | ||
|
|
4d023760ad | ||
|
|
10d9459f26 | ||
|
|
8b07a1e4a5 | ||
|
|
4afb0dfaaa | ||
|
|
f8260541ef | ||
|
|
6b794aa9a3 | ||
|
|
adb81616aa | ||
|
|
3982807b32 | ||
|
|
0a3a1b5ea6 | ||
|
|
df7710ded1 | ||
|
|
27f3993884 | ||
|
|
71bcafb243 | ||
|
|
1b6352573f | ||
|
|
7f86e488e4 | ||
|
|
37e08b0801 | ||
|
|
16bed1b811 | ||
|
|
bca4fe4f97 | ||
|
|
7409dbb77d | ||
|
|
774d830fff | ||
|
|
3a75002efc | ||
|
|
d9579853ad | ||
|
|
3fbcbbe7bc | ||
|
|
dbfe39991f | ||
|
|
6c164993bf | ||
|
|
2145fdb056 | ||
|
|
4472ed8394 | ||
|
|
e13bd5e3e6 | ||
|
|
0283be05db | ||
|
|
25eb992cf1 | ||
|
|
69e9465b93 | ||
|
|
700abe0500 | ||
|
|
0572ee6b35 | ||
|
|
e6826c7dfc | ||
|
|
ece347c825 | ||
|
|
b831cbce7e | ||
|
|
f9e2ed304b | ||
| 00515c5378 | |||
|
|
e3f5de4df5 | ||
|
|
26b65d63a8 | ||
| 4113d9cfd0 | |||
| 7fa2f096df | |||
| fcecf08ac0 | |||
| af6048de93 | |||
| d47b6047e5 | |||
| c525516a95 | |||
| 0eaa4b6fd2 | |||
| 2921e389df | |||
| 522d00bd52 | |||
| 821aae706d | |||
| 18d1a16b0c | |||
| 9c0ec67ccf | |||
| f0768027c9 | |||
| 80f22f731f | |||
| 81a3d5f8ff | |||
| 69fc6790ae | |||
| 5db68b6bb7 | |||
| 091d7aa863 | |||
| 582bdd698a | |||
| 726156843e | |||
| 846f85e2f8 | |||
| ca47013c5a | |||
| 82357f2ecc | |||
| c3cc5f7465 | |||
| 1888b4a4ae | |||
| 1edc88f14b | |||
| 0966ec124b | |||
| 05c6cd7739 | |||
| 2c37e05ff7 | |||
|
|
0cfb80a164 | ||
| 11b0a58351 | |||
| 869a7c21b4 | |||
| 17dd83de10 | |||
| bad1fb2552 | |||
| 5344d9cd5b | |||
| 89c43cd9a7 | |||
| 0d4a7e3e42 | |||
| d689045002 | |||
|
|
1efed08a39 | ||
|
|
56e5cb1f25 | ||
|
|
453d11c64c |
2
.gitignore
vendored
2
.gitignore
vendored
@ -21,6 +21,8 @@ coverage/*
|
|||||||
**/*.config
|
**/*.config
|
||||||
**/*.creator
|
**/*.creator
|
||||||
*.log
|
*.log
|
||||||
|
*.tmp
|
||||||
|
*.tmp.*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
bin/florincoin*
|
bin/florincoin*
|
||||||
bin/SHA256SUMS.asc
|
bin/SHA256SUMS.asc
|
||||||
|
|||||||
@ -12,7 +12,7 @@ var dbLocation = process.argv[2];
|
|||||||
|
|
||||||
console.log('Using db location: ', dbLocation);
|
console.log('Using db location: ', dbLocation);
|
||||||
|
|
||||||
var addressPrefix = Buffer.from('0006', 'hex');
|
var addressPrefix = new Buffer('0006', 'hex');
|
||||||
|
|
||||||
var startAddress = new Array(35).join('0');
|
var startAddress = new Array(35).join('0');
|
||||||
var endAddress = new Array(35).join('f');
|
var endAddress = new Array(35).join('f');
|
||||||
|
|||||||
@ -7,19 +7,19 @@ var dbPath = '/Users/chrisk/.bwdb/flocore-node.db';
|
|||||||
var flocore = require('flocore-lib');
|
var flocore = require('flocore-lib');
|
||||||
var db = levelup(dbPath, {keyEncoding: 'binary', valueEncoding: 'binary'});
|
var db = levelup(dbPath, {keyEncoding: 'binary', valueEncoding: 'binary'});
|
||||||
|
|
||||||
var prefix = Buffer.from('0002', 'hex');
|
var prefix = new Buffer('0002', 'hex');
|
||||||
var encoding = new Encoding(prefix);
|
var encoding = new Encoding(prefix);
|
||||||
var address = '1MfDRRVVKXUe5KNVZzu8CBzUZDHTTYZM94';
|
var address = '1MfDRRVVKXUe5KNVZzu8CBzUZDHTTYZM94';
|
||||||
var addressLength = Buffer.alloc(1);
|
var addressLength = new Buffer(1);
|
||||||
addressLength.writeUInt8(address.length);
|
addressLength.writeUInt8(address.length);
|
||||||
|
|
||||||
//var startBuffer = prefix;
|
//var startBuffer = prefix;
|
||||||
//var endBuffer = Buffer.concat([prefix, Buffer.from('ff', 'hex')]);
|
//var endBuffer = Buffer.concat([prefix, new Buffer('ff', 'hex')]);
|
||||||
|
|
||||||
//var startBuffer = Buffer.concat([prefix, addressLength, Buffer.from(address, 'utf8'), Buffer.from('00', 'hex')]);
|
//var startBuffer = Buffer.concat([prefix, addressLength, new Buffer(address, 'utf8'), new Buffer('00', 'hex')]);
|
||||||
//var endBuffer = Buffer.concat([prefix, addressLength, Buffer.from(address, 'utf8'), Buffer.from('01', 'hex')]);
|
//var endBuffer = Buffer.concat([prefix, addressLength, new Buffer(address, 'utf8'), new Buffer('01', 'hex')]);
|
||||||
var start = Buffer.concat([prefix, Buffer.from('0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9', 'hex')]);
|
var start = Buffer.concat([prefix, new Buffer('0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9', 'hex')]);
|
||||||
var end = Buffer.concat([prefix, Buffer.from('0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9', 'hex'), Buffer.from('01', 'hex')]);
|
var end = Buffer.concat([prefix, new Buffer('0437cd7f8525ceed2324359c2d0ba26006d92d856a9c20fa0241106ee5a597c9', 'hex'), new Buffer('01', 'hex')]);
|
||||||
var stream = db.createReadStream({
|
var stream = db.createReadStream({
|
||||||
gte: start,
|
gte: start,
|
||||||
lt: end
|
lt: end
|
||||||
|
|||||||
@ -8,6 +8,6 @@ module.exports = {
|
|||||||
testnet: '9b7bc86236c34b5e3a39367c036b7fe8807a966c22a7a1f0da2a198a27e03731', //this is testnet3
|
testnet: '9b7bc86236c34b5e3a39367c036b7fe8807a966c22a7a1f0da2a198a27e03731', //this is testnet3
|
||||||
testnet5: '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943' //this is testnet5
|
testnet5: '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943' //this is testnet5
|
||||||
},
|
},
|
||||||
DB_PREFIX: Buffer.from('ffff', 'hex')
|
DB_PREFIX: new Buffer('ffff', 'hex')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -212,12 +212,13 @@ function exitHandler(options, _process, node, err) {
|
|||||||
if(err.stack) {
|
if(err.stack) {
|
||||||
log.error(err.stack);
|
log.error(err.stack);
|
||||||
}
|
}
|
||||||
node.stop(function(err) {
|
if(options.exit)
|
||||||
if(err) {
|
node.stop(function(err) {
|
||||||
log.error('Failed to stop services: ' + err);
|
if(err) {
|
||||||
}
|
log.error('Failed to stop services: ' + err);
|
||||||
_process.exit(-1);
|
}
|
||||||
});
|
_process.exit(-1);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// Handle SIGINT (Ctrl+C)
|
// Handle SIGINT (Ctrl+C)
|
||||||
if (options.sigint) {
|
if (options.sigint) {
|
||||||
@ -229,7 +230,7 @@ function exitHandler(options, _process, node, err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function registerExitHandlers(_process, node) {
|
function registerExitHandlers(_process, node) {
|
||||||
_process.on('uncaughtException', exitHandler.bind(null, {exit:true}, _process, node));
|
_process.on('uncaughtException', exitHandler.bind(null, {exit:false}, _process, node));
|
||||||
_process.on('SIGINT', exitHandler.bind(null, {sigint:true}, _process, node));
|
_process.on('SIGINT', exitHandler.bind(null, {sigint:true}, _process, node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,36 +2,38 @@
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this.servicePrefix = servicePrefix;
|
this.servicePrefix = servicePrefix;
|
||||||
|
this.addressIndex = new Buffer('00', 'hex');
|
||||||
|
this.utxoIndex = new Buffer('01', 'hex');
|
||||||
|
this.addressCache = new Buffer('fe', 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
Encoding.prototype.encodeAddressIndexKey = function(address, height, txid, index, input, timestamp) {
|
Encoding.prototype.encodeAddressIndexKey = function(address, height, txid, index, input, timestamp) {
|
||||||
var prefix = Buffer.from('00', 'hex');
|
var buffers = [this.servicePrefix, this.addressIndex];
|
||||||
var buffers = [this.servicePrefix, prefix];
|
|
||||||
|
|
||||||
var addressSizeBuffer = Buffer.alloc(1);
|
var addressSizeBuffer = new Buffer(1);
|
||||||
addressSizeBuffer.writeUInt8(address.length);
|
addressSizeBuffer.writeUInt8(address.length);
|
||||||
var addressBuffer = Buffer.from(address, 'utf8');
|
var addressBuffer = new Buffer(address, 'utf8');
|
||||||
|
|
||||||
buffers.push(addressSizeBuffer);
|
buffers.push(addressSizeBuffer);
|
||||||
buffers.push(addressBuffer);
|
buffers.push(addressBuffer);
|
||||||
|
|
||||||
var heightBuffer = Buffer.alloc(4);
|
var heightBuffer = new Buffer(4);
|
||||||
heightBuffer.writeUInt32BE(height || 0);
|
heightBuffer.writeUInt32BE(height || 0);
|
||||||
buffers.push(heightBuffer);
|
buffers.push(heightBuffer);
|
||||||
|
|
||||||
var txidBuffer = Buffer.from(txid || Array(65).join('0'), 'hex');
|
var txidBuffer = new Buffer(txid || Array(65).join('0'), 'hex');
|
||||||
buffers.push(txidBuffer);
|
buffers.push(txidBuffer);
|
||||||
|
|
||||||
var indexBuffer = Buffer.alloc(4);
|
var indexBuffer = new Buffer(4);
|
||||||
indexBuffer.writeUInt32BE(index || 0);
|
indexBuffer.writeUInt32BE(index || 0);
|
||||||
buffers.push(indexBuffer);
|
buffers.push(indexBuffer);
|
||||||
|
|
||||||
// this is whether the address appears in an input (1) or output (0)
|
// this is whether the address appears in an input (1) or output (0)
|
||||||
var inputBuffer = Buffer.alloc(1);
|
var inputBuffer = new Buffer(1);
|
||||||
inputBuffer.writeUInt8(input || 0);
|
inputBuffer.writeUInt8(input || 0);
|
||||||
buffers.push(inputBuffer);
|
buffers.push(inputBuffer);
|
||||||
|
|
||||||
var timestampBuffer = Buffer.alloc(4);
|
var timestampBuffer = new Buffer(4);
|
||||||
timestampBuffer.writeUInt32BE(timestamp || 0);
|
timestampBuffer.writeUInt32BE(timestamp || 0);
|
||||||
buffers.push(timestampBuffer);
|
buffers.push(timestampBuffer);
|
||||||
|
|
||||||
@ -58,20 +60,19 @@ Encoding.prototype.decodeAddressIndexKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
|
||||||
var prefix = Buffer.from('01', 'hex');
|
var buffers = [this.servicePrefix, this.utxoIndex];
|
||||||
var buffers = [this.servicePrefix, prefix];
|
|
||||||
|
|
||||||
var addressSizeBuffer = Buffer.alloc(1);
|
var addressSizeBuffer = new Buffer(1);
|
||||||
addressSizeBuffer.writeUInt8(address.length);
|
addressSizeBuffer.writeUInt8(address.length);
|
||||||
var addressBuffer = Buffer.from(address, 'utf8');
|
var addressBuffer = new Buffer(address, 'utf8');
|
||||||
|
|
||||||
buffers.push(addressSizeBuffer);
|
buffers.push(addressSizeBuffer);
|
||||||
buffers.push(addressBuffer);
|
buffers.push(addressBuffer);
|
||||||
|
|
||||||
var txidBuffer = Buffer.from(txid || new Array(65).join('0'), 'hex');
|
var txidBuffer = new Buffer(txid || new Array(65).join('0'), 'hex');
|
||||||
buffers.push(txidBuffer);
|
buffers.push(txidBuffer);
|
||||||
|
|
||||||
var outputIndexBuffer = Buffer.alloc(4);
|
var outputIndexBuffer = new Buffer(4);
|
||||||
outputIndexBuffer.writeUInt32BE(outputIndex || 0);
|
outputIndexBuffer.writeUInt32BE(outputIndex || 0);
|
||||||
buffers.push(outputIndexBuffer);
|
buffers.push(outputIndexBuffer);
|
||||||
|
|
||||||
@ -92,11 +93,11 @@ Encoding.prototype.decodeUtxoIndexKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeUtxoIndexValue = function(height, satoshis, timestamp, scriptBuffer) {
|
Encoding.prototype.encodeUtxoIndexValue = function(height, satoshis, timestamp, scriptBuffer) {
|
||||||
var heightBuffer = Buffer.alloc(4);
|
var heightBuffer = new Buffer(4);
|
||||||
heightBuffer.writeUInt32BE(height);
|
heightBuffer.writeUInt32BE(height);
|
||||||
var satoshisBuffer = Buffer.alloc(8);
|
var satoshisBuffer = new Buffer(8);
|
||||||
satoshisBuffer.writeDoubleBE(satoshis);
|
satoshisBuffer.writeDoubleBE(satoshis);
|
||||||
var timestampBuffer = Buffer.alloc(4);
|
var timestampBuffer = new Buffer(4);
|
||||||
timestampBuffer.writeUInt32BE(timestamp || 0);
|
timestampBuffer.writeUInt32BE(timestamp || 0);
|
||||||
return Buffer.concat([heightBuffer, satoshisBuffer, timestampBuffer, scriptBuffer]);
|
return Buffer.concat([heightBuffer, satoshisBuffer, timestampBuffer, scriptBuffer]);
|
||||||
};
|
};
|
||||||
@ -114,5 +115,53 @@ Encoding.prototype.decodeUtxoIndexValue = function(buffer) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Encoding.prototype.encodeAddressCacheKey = function(address) {
|
||||||
|
return Buffer.concat([this.servicePrefix, this.addressCache, new Buffer(address, 'utf8')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoding.prototype.decodeAddressCacheKey = function(buffer) {
|
||||||
|
return buffer.slice(3).toString('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoding.prototype.encodeAddressCacheValue = function(lastTx, lastBlock, balance, received, sent, txApperances) {
|
||||||
|
|
||||||
|
var buffer = [];
|
||||||
|
|
||||||
|
var balanceBuffer = new Buffer(8);
|
||||||
|
balanceBuffer.writeBigUInt64BE(BigInt(balance));
|
||||||
|
buffer.push(balanceBuffer);
|
||||||
|
|
||||||
|
var receivedBuffer = new Buffer(8);
|
||||||
|
receivedBuffer.writeBigUInt64BE(BigInt(received));
|
||||||
|
buffer.push(receivedBuffer);
|
||||||
|
|
||||||
|
var sentBuffer = new Buffer(8);
|
||||||
|
sentBuffer.writeBigUInt64BE(BigInt(sent));
|
||||||
|
buffer.push(sentBuffer);
|
||||||
|
|
||||||
|
var txApperancesBuffer = new Buffer(4);
|
||||||
|
txApperancesBuffer.writeUInt32BE(txApperances);
|
||||||
|
buffer.push(txApperancesBuffer);
|
||||||
|
|
||||||
|
var txidBuffer = new Buffer(lastTx, 'hex');
|
||||||
|
buffer.push(txidBuffer);
|
||||||
|
|
||||||
|
var blkBuffer = new Buffer(lastBlock, 'hex');
|
||||||
|
buffer.push(blkBuffer);
|
||||||
|
|
||||||
|
return Buffer.concat(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Encoding.prototype.decodeAddressCacheValue = function(buffer) {
|
||||||
|
|
||||||
|
var balance = parseInt(buffer.readBigUInt64BE(0));
|
||||||
|
var received = parseInt(buffer.readBigUInt64BE(8));
|
||||||
|
var sent = parseInt(buffer.readBigUInt64BE(16));
|
||||||
|
var txApperances = buffer.readUInt32BE(24);
|
||||||
|
var lastTx = buffer.slice(28, 60).toString('hex'); //28 + 32 (tx hash buffer length) = 60
|
||||||
|
var lastBlock = buffer.slice(60).toString('hex');
|
||||||
|
return { lastTx, lastBlock, balance, received, sent, txApperances };
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = Encoding;
|
module.exports = Encoding;
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,9 @@ var utils = require('../../utils');
|
|||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
var XXHash = require('xxhash');
|
var XXHash = require('xxhash');
|
||||||
|
|
||||||
|
const MAX_TX_QUERY_LIMIT_HISTORY = 1000;
|
||||||
|
const MAX_TX_QUERY_LIMIT_UTXO = 1000;
|
||||||
|
const MAX_TX_QUERY_LIMIT_SUMMARY = 500;
|
||||||
|
|
||||||
// See rationale about this cache at function getTxList(next)
|
// See rationale about this cache at function getTxList(next)
|
||||||
const TXID_LIST_CACHE_ITEMS = 250; // nr of items (this translates to: consecutive
|
const TXID_LIST_CACHE_ITEMS = 250; // nr of items (this translates to: consecutive
|
||||||
@ -67,8 +69,8 @@ AddressService.dependencies = [
|
|||||||
// then I would pass back [tx1, tx2] in that order
|
// then I would pass back [tx1, tx2] in that order
|
||||||
//
|
//
|
||||||
// Instead of passing addresses, with from>0, options.cacheKey can be used to define the address set.
|
// Instead of passing addresses, with from>0, options.cacheKey can be used to define the address set.
|
||||||
//
|
//(old one: non-optimized for large data)
|
||||||
AddressService.prototype.getAddressHistory = function(addresses, options, callback) {
|
AddressService.prototype.__getAddressHistory = function(addresses, options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var cacheUsed = false;
|
var cacheUsed = false;
|
||||||
|
|
||||||
@ -173,8 +175,106 @@ AddressService.prototype.getAddressHistory = function(addresses, options, callba
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressService.prototype.getAddressHistory = function(addresses, options, streamer, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
//options.from = options.from || 0; //Deprecated, use `after` and `before` option
|
||||||
|
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option
|
||||||
|
|
||||||
|
if(!_.isFunction(callback)){ //if only 3 args, then streamer is callback
|
||||||
|
callback = streamer;
|
||||||
|
streamer = () => null; //NULL fn
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(options.queryMempool)) {
|
||||||
|
options.queryMempool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(options.mempoolOnly)) {
|
||||||
|
options.mempoolOnly = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_.isUndefined(options.reverse)) {
|
||||||
|
options.reverse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var old_support = false;
|
||||||
|
//Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use)
|
||||||
|
if(!_.isUndefined(options.from) || !_.isUndefined(options.to)) {
|
||||||
|
old_support = true;
|
||||||
|
options.from = options.from || 0;
|
||||||
|
options.to = options.to || 0xffffffff; //Max value of to will actually be MAX_TX_QUERY_LIMIT_HISTORY
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isString(addresses)) {
|
||||||
|
addresses = [addresses];
|
||||||
|
}
|
||||||
|
|
||||||
|
var results = {
|
||||||
|
totalCount: 0,
|
||||||
|
items: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
async.eachLimit(addresses, 4, function(address, next) {
|
||||||
|
|
||||||
|
var addr_options = Object.assign({}, options), addr_count = 0;
|
||||||
|
|
||||||
|
self._streamAddressSummary(address, addr_options, function(err, tx){
|
||||||
|
|
||||||
|
if(err)
|
||||||
|
return log.error(err);
|
||||||
|
|
||||||
|
addr_count++;
|
||||||
|
|
||||||
|
if(!results.items.some(x => x.txid() === tx.txid())) {//add only if tx not already in array
|
||||||
|
if(!options.reverse)
|
||||||
|
results.items.unshift(tx); //using unshift, so that recent tx (low) are at front
|
||||||
|
else
|
||||||
|
results.items.push(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(results.items.length > MAX_TX_QUERY_LIMIT_HISTORY) { //remove items from array when overflown
|
||||||
|
results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid()));
|
||||||
|
let del_count = results.items.length - MAX_TX_QUERY_LIMIT_HISTORY;
|
||||||
|
let start_index = (old_support || options.reverse) ? MAX_TX_QUERY_LIMIT_HISTORY : 0;
|
||||||
|
results.items.splice(start_index, del_count);
|
||||||
|
|
||||||
|
results.incomplete = true;
|
||||||
|
|
||||||
|
if(!old_support && addr_count >= MAX_TX_QUERY_LIMIT_HISTORY)
|
||||||
|
addr_options.flag_stop = true; //limit has reached, stop quering db for more tx
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
streamer(null, tx);
|
||||||
|
|
||||||
|
}, next);
|
||||||
|
|
||||||
|
}, function(err) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
//sort items in desc block-height, then asc txid (if same height)
|
||||||
|
results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid()));
|
||||||
|
results.totalCount = results.items.length ;
|
||||||
|
|
||||||
|
//Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use)
|
||||||
|
if(old_support) {
|
||||||
|
results.items = results.items.slice(options.from, options.to);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, results);
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
// this is basically the same as _getAddressHistory apart from the summary
|
// this is basically the same as _getAddressHistory apart from the summary
|
||||||
AddressService.prototype.getAddressSummary = function(address, options, callback) {
|
//(old one: non-optimized for large data)
|
||||||
|
AddressService.prototype.__getAddressSummary = function(address, options, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -200,7 +300,7 @@ AddressService.prototype.getAddressSummary = function(address, options, callback
|
|||||||
txApperances: 0,
|
txApperances: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getAddressHistory(address, options, function(err, results) {
|
self.__getAddressHistory(address, options, function(err, results) { //old fn
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
@ -218,6 +318,229 @@ AddressService.prototype.getAddressSummary = function(address, options, callback
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressService.prototype.getAddressSummary = function(address, options, streamer, callback) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
//options.from = options.from || 0; //Deprecated, use `after` and `before` option
|
||||||
|
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option
|
||||||
|
|
||||||
|
if (_.isUndefined(options.queryMempool)) {
|
||||||
|
options.queryMempool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!_.isFunction(callback)){ //if only 3 args, then streamer is callback
|
||||||
|
callback = streamer;
|
||||||
|
streamer = () => null; //NULL fn
|
||||||
|
}
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
var result = {
|
||||||
|
addrStr: address,
|
||||||
|
balance: 0,
|
||||||
|
balanceSat: 0,
|
||||||
|
totalReceived: 0,
|
||||||
|
totalReceivedSat: 0,
|
||||||
|
totalSent: 0,
|
||||||
|
totalSentSat: 0,
|
||||||
|
unconfirmedBalance: 0,
|
||||||
|
unconfirmedBalanceSat: 0,
|
||||||
|
unconfirmedTxApperances: 0,
|
||||||
|
txApperances: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
var useCache = _.isUndefined(options.after) && _.isUndefined(options.before);
|
||||||
|
var lastTx, lastBlock;
|
||||||
|
|
||||||
|
self._loadCache(address, result, useCache, function(err, lastCachedTx) {
|
||||||
|
if(err)
|
||||||
|
log.error(err);
|
||||||
|
|
||||||
|
if(!_.isUndefined(lastCachedTx))
|
||||||
|
options.after = lastCachedTx;
|
||||||
|
|
||||||
|
self._streamAddressSummary(address, options, function(err, tx) {
|
||||||
|
|
||||||
|
if(err)
|
||||||
|
return log.error(err);
|
||||||
|
|
||||||
|
if(tx) {
|
||||||
|
count++;
|
||||||
|
self._aggregateAddressSummaryResult(tx, address, result, options);
|
||||||
|
|
||||||
|
if(tx.confirmations) {
|
||||||
|
lastTx = tx.txid();
|
||||||
|
lastBlock = tx.blockhash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count >= MAX_TX_QUERY_LIMIT_SUMMARY) {//stop quering db when limit reached
|
||||||
|
options.flag_stop = true;
|
||||||
|
result.incomplete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
streamer(null, tx);
|
||||||
|
|
||||||
|
}, function(err) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.balanceSat = parseInt(result.balanceSat.toFixed());
|
||||||
|
result.totalReceivedSat = parseInt(result.totalReceivedSat.toFixed());
|
||||||
|
result.totalSentSat = parseInt(result.totalSentSat.toFixed());
|
||||||
|
result.txApperances = parseInt(result.txApperances.toFixed());
|
||||||
|
result.unconfirmedBalanceSat = parseInt(result.unconfirmedBalanceSat.toFixed());
|
||||||
|
result.unconfirmedTxApperances = parseInt(result.unconfirmedTxApperances.toFixed());
|
||||||
|
|
||||||
|
result.balance = Unit.fromSatoshis(result.balanceSat).toBTC();
|
||||||
|
result.totalReceived = Unit.fromSatoshis(result.totalReceivedSat).toBTC();
|
||||||
|
result.totalSent = Unit.fromSatoshis(result.totalSentSat).toBTC();
|
||||||
|
result.unconfirmedBalance = Unit.fromSatoshis(result.unconfirmedBalanceSat).toBTC();
|
||||||
|
|
||||||
|
result.lastItem = lastTx;
|
||||||
|
|
||||||
|
callback(null, result);
|
||||||
|
|
||||||
|
//store in cache if needed
|
||||||
|
if(useCache) {
|
||||||
|
if(result.incomplete) //full summary needs to be calculated in background
|
||||||
|
self._cacheSummaryInBackground(address, lastTx, lastBlock, result);
|
||||||
|
else if (!_.isUndefined(lastCachedTx) && !_.isUndefined(lastTx)
|
||||||
|
&& lastTx != lastCachedTx && !self._cacheInstance.has(address)) //update cache if needed
|
||||||
|
self._storeCache(address, lastTx, lastBlock, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressService.prototype._cacheInstance = new Set();
|
||||||
|
AddressService.prototype._cacheSummaryInBackground = function(address, lastTx, lastBlock, result){
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
if(self._cacheInstance.has(address))
|
||||||
|
return;
|
||||||
|
|
||||||
|
self._cacheInstance.add(address);
|
||||||
|
|
||||||
|
const cache = {
|
||||||
|
balanceSat: result.balanceSat,
|
||||||
|
totalReceivedSat: result.totalReceivedSat,
|
||||||
|
totalSentSat: result.totalSentSat,
|
||||||
|
txApperances: result.txApperances,
|
||||||
|
unconfirmedBalanceSat: 0, //unconfirmed (mempool) values should not be cached
|
||||||
|
unconfirmedTxApperances: 0
|
||||||
|
};
|
||||||
|
const options = { queryMempool: false, after: lastTx, noTxList: true };
|
||||||
|
|
||||||
|
self._streamAddressSummary(address, options, function(err, tx) {
|
||||||
|
|
||||||
|
if(err)
|
||||||
|
return log.error(err);
|
||||||
|
|
||||||
|
if(tx) {
|
||||||
|
self._aggregateAddressSummaryResult(tx, address, cache, options);
|
||||||
|
if(tx.confirmations){
|
||||||
|
lastTx = tx.txid();
|
||||||
|
lastBlock = tx.blockhash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, function(err) {
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return log.error(err);
|
||||||
|
|
||||||
|
cache.balanceSat = parseInt(cache.balanceSat.toFixed());
|
||||||
|
cache.totalReceivedSat = parseInt(cache.totalReceivedSat.toFixed());
|
||||||
|
cache.totalSentSat = parseInt(cache.totalSentSat.toFixed());
|
||||||
|
cache.txApperances = parseInt(cache.txApperances.toFixed());
|
||||||
|
|
||||||
|
if(!_.isUndefined(lastTx))
|
||||||
|
self._storeCache(address, lastTx, lastBlock, cache);
|
||||||
|
|
||||||
|
self._cacheInstance.delete(address); //remove from running instance
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressService.prototype._storeCache = function(address, lastCacheTx, lastCacheBlock, result, callback) {
|
||||||
|
const self = this;
|
||||||
|
var key = self._encoding.encodeAddressCacheKey(address);
|
||||||
|
var value = self._encoding.encodeAddressCacheValue(lastCacheTx, lastCacheBlock, result.balanceSat, result.totalReceivedSat, result.totalSentSat, result.txApperances)
|
||||||
|
|
||||||
|
if(!_.isFunction(callback)) //if callback is not passed, call a empty function
|
||||||
|
callback = () => null;
|
||||||
|
|
||||||
|
self._db.put(key, value, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressService.prototype._loadCache = function(address, result, useCache, callback) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
if(!useCache) //skip if useCache is false (cases like 'after' and/or 'before' parameter is used by client)
|
||||||
|
return callback();
|
||||||
|
|
||||||
|
var key = self._encoding.encodeAddressCacheKey(address);
|
||||||
|
self._db.get(key, function(err, value) {
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
if (!value) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
var addressCache = self._encoding.decodeAddressCacheValue(value);
|
||||||
|
|
||||||
|
var lastCacheTx = addressCache.lastTx, lastCacheBlock = addressCache.lastBlock
|
||||||
|
|
||||||
|
self._block.getBlock(lastCacheBlock, function(err, block) {
|
||||||
|
|
||||||
|
if(err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!block) { //block not found, probably removed in reorg.
|
||||||
|
//delete the existing cache and recalc values freshly
|
||||||
|
self._deleteCache(address, function() {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//values are in satoshis
|
||||||
|
result.balanceSat = addressCache.balance;
|
||||||
|
result.totalReceivedSat = addressCache.received;
|
||||||
|
result.totalSentSat = addressCache.sent;
|
||||||
|
result.txApperances = addressCache.txApperances;
|
||||||
|
|
||||||
|
callback(null, lastCacheTx);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressService.prototype._deleteCache = function(address, callback) {
|
||||||
|
const self = this;
|
||||||
|
var key = self._encoding.encodeAddressCacheKey(address);
|
||||||
|
|
||||||
|
if(!_.isFunction(callback)) //if callback is not passed, call a empty function
|
||||||
|
callback = () => null;
|
||||||
|
|
||||||
|
self._db.del(key, callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
AddressService.prototype._setOutputResults = function(tx, address, result) {
|
AddressService.prototype._setOutputResults = function(tx, address, result) {
|
||||||
|
|
||||||
for(var j = 0; j < tx.outputs.length; j++) {
|
for(var j = 0; j < tx.outputs.length; j++) {
|
||||||
@ -265,7 +588,6 @@ AddressService.prototype._getAddressSummaryResult = function(txs, address, resul
|
|||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
for(var i = 0; i < txs.length; i++) {
|
for(var i = 0; i < txs.length; i++) {
|
||||||
|
|
||||||
var tx = txs[i];
|
var tx = txs[i];
|
||||||
|
|
||||||
self._setOutputResults(tx, address, result);
|
self._setOutputResults(tx, address, result);
|
||||||
@ -283,6 +605,110 @@ AddressService.prototype._getAddressSummaryResult = function(txs, address, resul
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressService.prototype._getOccurrenceCount = function(tx, address) {
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
for(var i = 0; i < tx.inputs.length; i++) {
|
||||||
|
|
||||||
|
var input = tx.inputs[i];
|
||||||
|
|
||||||
|
if(utils.getAddress(input, this._network) === address)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var j = 0; j < tx.outputs.length; j++) {
|
||||||
|
|
||||||
|
var output = tx.outputs[j];
|
||||||
|
|
||||||
|
if(utils.getAddress(output, this._network) === address)
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AddressService.prototype._getOutputResults = function(tx, address) {
|
||||||
|
|
||||||
|
let value = 0;
|
||||||
|
|
||||||
|
for(var j = 0; j < tx.outputs.length; j++) {
|
||||||
|
|
||||||
|
var output = tx.outputs[j];
|
||||||
|
|
||||||
|
if (utils.getAddress(output, this._network) === address)
|
||||||
|
value += output.value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressService.prototype._getInputResults = function(tx, address) {
|
||||||
|
|
||||||
|
let value = 0;
|
||||||
|
|
||||||
|
for(var i = 0; i < tx.inputs.length; i++) {
|
||||||
|
|
||||||
|
var input = tx.inputs[i];
|
||||||
|
|
||||||
|
if (utils.getAddress(input, this._network) === address)
|
||||||
|
value += tx.__inputValues[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressService.prototype._aggregateAddressSummaryResult = function (tx, address, result, options) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
let output_val = self._getOutputResults(tx, address);
|
||||||
|
let input_val = self._getInputResults(tx, address);
|
||||||
|
|
||||||
|
//aggregate the result
|
||||||
|
|
||||||
|
if(tx.confirmations) {
|
||||||
|
|
||||||
|
result.txApperances++;
|
||||||
|
|
||||||
|
result.totalReceivedSat += output_val;
|
||||||
|
result.balanceSat += output_val;
|
||||||
|
|
||||||
|
result.totalSentSat += input_val;
|
||||||
|
result.balanceSat -= input_val;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result.unconfirmedTxApperances++;
|
||||||
|
result.unconfirmedBalanceSat += output_val;
|
||||||
|
result.unconfirmedBalanceSat -= input_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.noTxList) {
|
||||||
|
|
||||||
|
if (!result.transactions) {
|
||||||
|
result.transactions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let txid = tx.txid();
|
||||||
|
if(!result.transactions.includes(txid)) { //push txid only if its not in the array
|
||||||
|
|
||||||
|
result.transactions.unshift(txid); //using unshift, so that recent tx (low confirmation) are at front
|
||||||
|
|
||||||
|
if(result.transactions.length > MAX_TX_QUERY_LIMIT_SUMMARY)
|
||||||
|
result.transactions.pop(); //pop the oldest tx in list (when list limit is maxed out)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
AddressService.prototype.getAddressUnspentOutputs = function(address, options, callback) {
|
AddressService.prototype.getAddressUnspentOutputs = function(address, options, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -298,7 +724,7 @@ AddressService.prototype.getAddressUnspentOutputs = function(address, options, c
|
|||||||
var results = [];
|
var results = [];
|
||||||
|
|
||||||
var start = self._encoding.encodeUtxoIndexKey(address);
|
var start = self._encoding.encodeUtxoIndexKey(address);
|
||||||
var final = Buffer.from(new Array(73).join('f'), 'hex');
|
var final = new Buffer(new Array(73).join('f'), 'hex');
|
||||||
var end = Buffer.concat([ start.slice(0, -36), final ]);
|
var end = Buffer.concat([ start.slice(0, -36), final ]);
|
||||||
|
|
||||||
var criteria = {
|
var criteria = {
|
||||||
@ -365,6 +791,11 @@ AddressService.prototype.getAddressUnspentOutputs = function(address, options, c
|
|||||||
|
|
||||||
utxoStream.on('data', function(data) {
|
utxoStream.on('data', function(data) {
|
||||||
|
|
||||||
|
if(results.length >= MAX_TX_QUERY_LIMIT_UTXO) { //Max array limit reached, end response
|
||||||
|
utxoStream.emit('end');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var key = self._encoding.decodeUtxoIndexKey(data.key);
|
var key = self._encoding.decodeUtxoIndexKey(data.key);
|
||||||
var value = self._encoding.decodeUtxoIndexValue(data.value);
|
var value = self._encoding.decodeUtxoIndexValue(data.value);
|
||||||
|
|
||||||
@ -440,19 +871,21 @@ AddressService.prototype.stop = function(callback) {
|
|||||||
|
|
||||||
AddressService.prototype._getTxidStream = function(address, options) {
|
AddressService.prototype._getTxidStream = function(address, options) {
|
||||||
|
|
||||||
var start = this._encoding.encodeAddressIndexKey(address);
|
var criteria = {};
|
||||||
var end = Buffer.concat([
|
|
||||||
start.slice(0, address.length + 4),
|
|
||||||
options.endHeightBuf,
|
|
||||||
Buffer.from(new Array(83).join('f'), 'hex')
|
|
||||||
]);
|
|
||||||
|
|
||||||
var criteria = {
|
if(options.after)
|
||||||
gte: start,
|
criteria.gt = this._encoding.encodeAddressIndexKey(address, options.start, options.after, 0xffffffff, 1, 0xffffffff); //0xffffffff is for getting after the txid
|
||||||
lte: end,
|
else
|
||||||
reverse: true // txids stream from low confirmations to high confirmations
|
criteria.gte = this._encoding.encodeAddressIndexKey(address, options.start);
|
||||||
};
|
|
||||||
|
|
||||||
|
if(options.before)
|
||||||
|
criteria.lt = this._encoding.encodeAddressIndexKey(address, options.end, options.before); //get before the txid
|
||||||
|
else
|
||||||
|
criteria.lte = this._encoding.encodeAddressIndexKey(address, options.end, Array(65).join('f'), 0xffffffff, 1, 0xffffffff);
|
||||||
|
|
||||||
|
//reverse option can be used explictly when latest tx are required
|
||||||
|
if(options.reverse)
|
||||||
|
criteria.reverse = true;
|
||||||
// txid stream
|
// txid stream
|
||||||
var txidStream = this._db.createKeyStream(criteria);
|
var txidStream = this._db.createKeyStream(criteria);
|
||||||
|
|
||||||
@ -463,6 +896,7 @@ AddressService.prototype._getTxidStream = function(address, options) {
|
|||||||
return txidStream;
|
return txidStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//(used by old fn)
|
||||||
AddressService.prototype._getAddressTxHistory = function(options, callback) {
|
AddressService.prototype._getAddressTxHistory = function(options, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -491,6 +925,7 @@ AddressService.prototype._getAddressTxHistory = function(options, callback) {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//(used by old fn)
|
||||||
AddressService.prototype._getAddressTxidHistory = function(address, options, callback) {
|
AddressService.prototype._getAddressTxidHistory = function(address, options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -500,9 +935,6 @@ AddressService.prototype._getAddressTxidHistory = function(address, options, cal
|
|||||||
|
|
||||||
var results = [];
|
var results = [];
|
||||||
|
|
||||||
options.endHeightBuf = Buffer.alloc(4);
|
|
||||||
options.endHeightBuf.writeUInt32BE(options.end);
|
|
||||||
|
|
||||||
if (_.isUndefined(options.queryMempool)) {
|
if (_.isUndefined(options.queryMempool)) {
|
||||||
options.queryMempool = true;
|
options.queryMempool = true;
|
||||||
}
|
}
|
||||||
@ -551,7 +983,15 @@ AddressService.prototype._getAddressTxidHistory = function(address, options, cal
|
|||||||
|
|
||||||
txIdTransformStream._transform = function(chunk, enc, callback) {
|
txIdTransformStream._transform = function(chunk, enc, callback) {
|
||||||
var txInfo = self._encoding.decodeAddressIndexKey(chunk);
|
var txInfo = self._encoding.decodeAddressIndexKey(chunk);
|
||||||
results.push({ txid: txInfo.txid, height: txInfo.height });
|
|
||||||
|
if(results.length >= MAX_TX_QUERY_LIMIT_HISTORY) { //Max array limit reached, end response
|
||||||
|
txIdTransformStream.emit('end');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!results.some(r => r.txid == txInfo.txid)) //add txid to array only if its not already there
|
||||||
|
results.push({ txid: txInfo.txid, height: txInfo.height });
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -563,6 +1003,225 @@ AddressService.prototype._getAddressTxidHistory = function(address, options, cal
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddressService.prototype._streamAddressSummary = function(address, options, streamer, callback) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
options.start = options.start || 0;
|
||||||
|
options.end = options.end || 0xffffffff;
|
||||||
|
|
||||||
|
//options.from = options.from || 0; //Deprecated, use `after` and `before` option
|
||||||
|
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option
|
||||||
|
|
||||||
|
if (_.isUndefined(options.queryMempool)) {
|
||||||
|
options.queryMempool = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(options.mempoolOnly)) {
|
||||||
|
options.mempoolOnly = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(options.reverse)) {
|
||||||
|
options.reverse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//declare the queue to process tx data
|
||||||
|
var tmpTxList = {}; //store processed txid temporarily to ignore duplication
|
||||||
|
|
||||||
|
var q = async.queue(function(id, cb) {
|
||||||
|
|
||||||
|
//duplication finding
|
||||||
|
if(id.txid in tmpTxList){
|
||||||
|
|
||||||
|
tmpTxList[id.txid][0]++;
|
||||||
|
|
||||||
|
if(tmpTxList[id.txid][1] !== null && tmpTxList[id.txid][0] >= tmpTxList[id.txid][1]) //all duplications are found for this txid
|
||||||
|
delete tmpTxList[id.txid];
|
||||||
|
|
||||||
|
return cb();
|
||||||
|
|
||||||
|
} else tmpTxList[id.txid] = [1, null];
|
||||||
|
|
||||||
|
if (id.height === 0xffffffff) {
|
||||||
|
|
||||||
|
return self._mempool.getMempoolTransaction(id.txid, function(err, tx) {
|
||||||
|
|
||||||
|
if (err || !tx) {
|
||||||
|
return cb(err || new Error('Address Service: could not find tx: ' + id.txid));
|
||||||
|
}
|
||||||
|
self._transaction.setTxMetaInfo(tx, options, cb);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
self._transaction.getDetailedTransaction(id.txid, options, cb);
|
||||||
|
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
//q.pause(); //pause and wait until queue is set (not needed)
|
||||||
|
|
||||||
|
function chunkCallback(err, tx){
|
||||||
|
|
||||||
|
if(q.killed || (!err && !tx)) //no error or tx data (duplicate calls will have empty tx value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(tx){
|
||||||
|
let txid = tx.txid();
|
||||||
|
tmpTxList[txid][1] = self._getOccurrenceCount(tx, address);
|
||||||
|
|
||||||
|
if(tmpTxList[txid][0] >= tmpTxList[txid][1]) //all duplications are found for this txid
|
||||||
|
delete tmpTxList[txid];
|
||||||
|
}
|
||||||
|
|
||||||
|
streamer(err, tx);
|
||||||
|
|
||||||
|
if((err || options.flag_stop) && !q.killed){
|
||||||
|
|
||||||
|
q.kill();
|
||||||
|
q.killed = true;
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const waterfall_array = [];
|
||||||
|
|
||||||
|
waterfall_array.push(
|
||||||
|
//Find start height if `after` option is passed
|
||||||
|
function parse_after_id(next){
|
||||||
|
|
||||||
|
if(_.isUndefined(options.after)) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
self._transaction.getTransaction(options.after, options, function(err, tx) {
|
||||||
|
|
||||||
|
if(tx && tx.confirmations && tx.height >= options.start) {
|
||||||
|
|
||||||
|
options.start = tx.height;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
delete options.after;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
waterfall_array.push(
|
||||||
|
//Find end height if `before` option is passed
|
||||||
|
function parse_before_id(next){
|
||||||
|
|
||||||
|
if(_.isUndefined(options.before)) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
self._transaction.getTransaction(options.before, options, function(err, tx) {
|
||||||
|
|
||||||
|
if(tx && tx.confirmations && tx.height <= options.end) {
|
||||||
|
|
||||||
|
options.end = tx.height;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
delete options.before;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// stream the confirmed txids out of the address index
|
||||||
|
function query_confirmed_txids(next) {
|
||||||
|
|
||||||
|
if (options.mempoolOnly) { //Option to query from mempool only (ie, unconfirmed txs only)
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
var txIdTransformStream = new Transform({ objectMode: true });
|
||||||
|
|
||||||
|
txIdTransformStream._flush = function(cb) {
|
||||||
|
txIdTransformStream.emit('end');
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
txIdTransformStream.on('error', function(err) {
|
||||||
|
log.error('Address Service: txstream err: ' + err);
|
||||||
|
txIdTransformStream.unpipe();
|
||||||
|
});
|
||||||
|
|
||||||
|
txIdTransformStream.on('end', function() {
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
txIdTransformStream._transform = function(chunk, enc, cb) {
|
||||||
|
|
||||||
|
if(options.flag_stop)//stop data query
|
||||||
|
return txIdTransformStream.unpipe();
|
||||||
|
|
||||||
|
var txInfo = self._encoding.decodeAddressIndexKey(chunk);
|
||||||
|
q.push({ txid: txInfo.txid, height: txInfo.height }, chunkCallback);
|
||||||
|
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
var txidStream = self._getTxidStream(address, options);
|
||||||
|
txidStream.pipe(txIdTransformStream);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// query the mempool for relevant txs for this address
|
||||||
|
function query_mempool_txids(next) {
|
||||||
|
|
||||||
|
if (!options.queryMempool || !_.isUndefined(options.before)) { //if queryMempool=false or options.before is given a valid value, then do not query mempool
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
self._mempool.getTxidsByAddress(address, 'both', function(err, mempoolTxids) {
|
||||||
|
|
||||||
|
if (mempoolTxids.length <= 0) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
mempoolTxids.map(id => q.push(id, chunkCallback));
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.reverse){ //when queried txs in reverse key order, mempool first then confirmed
|
||||||
|
waterfall_array.push(query_mempool_txids);
|
||||||
|
waterfall_array.push(query_confirmed_txids);
|
||||||
|
} else { //when queried tx in key order, confirmed tx 1st, then mempool
|
||||||
|
waterfall_array.push(query_confirmed_txids);
|
||||||
|
waterfall_array.push(query_mempool_txids);
|
||||||
|
}
|
||||||
|
|
||||||
|
waterfall_array.push(
|
||||||
|
//wait for queue to complete
|
||||||
|
function end_fall(next) {
|
||||||
|
|
||||||
|
if(!q.started || q.idle()) //No tx in query (or) already finished querying
|
||||||
|
return next();
|
||||||
|
|
||||||
|
else
|
||||||
|
q.drain = () => next();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
async.waterfall(waterfall_array, callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
AddressService.prototype._removeBlock = function(block, callback) {
|
AddressService.prototype._removeBlock = function(block, callback) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|||||||
@ -242,7 +242,7 @@ ProcessSerial.prototype._write = function(block, enc, callback) {
|
|||||||
|
|
||||||
self.block.once('concurrentaddblock', function() {
|
self.block.once('concurrentaddblock', function() {
|
||||||
if(!check()) {
|
if(!check()) {
|
||||||
var err = new Error('Concurrent block ' + self.block.concurrentTip.__height + ' is less than ' + block.__height);
|
var err = 'Concurrent block ' + self.block.concurrentTip.__height + ' is less than ' + block.__height;
|
||||||
return self.emit('error', err);
|
return self.emit('error', err);
|
||||||
}
|
}
|
||||||
self._process(block, callback);
|
self._process(block, callback);
|
||||||
|
|||||||
@ -10,7 +10,7 @@ function Encoding(servicePrefix) {
|
|||||||
|
|
||||||
// ---- hash --> rawblock
|
// ---- hash --> rawblock
|
||||||
Encoding.prototype.encodeBlockKey = function(hash) {
|
Encoding.prototype.encodeBlockKey = function(hash) {
|
||||||
return Buffer.concat([ this._servicePrefix, Buffer.from(hash, 'hex') ]);
|
return Buffer.concat([ this._servicePrefix, new Buffer(hash, 'hex') ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeBlockKey = function(buffer) {
|
Encoding.prototype.decodeBlockKey = function(buffer) {
|
||||||
|
|||||||
@ -13,6 +13,8 @@ var bcoin = require('fcoin');
|
|||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
|
|
||||||
|
const MAX_IGNORED_BLOCK = 16; //Maximum ignored block allowed before trigging sync again
|
||||||
|
|
||||||
var BlockService = function(options) {
|
var BlockService = function(options) {
|
||||||
|
|
||||||
BaseService.call(this, options);
|
BaseService.call(this, options);
|
||||||
@ -231,8 +233,8 @@ BlockService.prototype._resetTip = function(callback) {
|
|||||||
self._header.getAllHeaders(function(err, headers) {
|
self._header.getAllHeaders(function(err, headers) {
|
||||||
|
|
||||||
if (err || !headers) {
|
if (err || !headers) {
|
||||||
return callback(err || new Error('headers required'));
|
log.error(err || 'headers required'); return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info('Block Service: retrieved all the headers for lookups.');
|
log.info('Block Service: retrieved all the headers for lookups.');
|
||||||
|
|
||||||
@ -252,13 +254,18 @@ BlockService.prototype._resetTip = function(callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_block) {
|
if (!_block) {
|
||||||
log.debug('Block Service: block: ' + header.hash + ' was not found, proceeding to older blocks.');
|
log.debug('Block Service: block: ' + header.hash + ' was not found, proceeding to older blocks.');
|
||||||
}
|
}
|
||||||
|
|
||||||
block = _block;
|
block = _block;
|
||||||
header = headers.getIndex(--height);
|
header = headers.getIndex(--height);
|
||||||
assert(header, 'Header not found for reset.');
|
|
||||||
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (header == false) {
|
||||||
|
log.error('Header not found for reset.');
|
||||||
|
}
|
||||||
|
// assert(header, 'Header not found for reset.');
|
||||||
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
log.debug('Block Service: trying block: ' + header.hash);
|
log.debug('Block Service: trying block: ' + header.hash);
|
||||||
@ -271,8 +278,8 @@ BlockService.prototype._resetTip = function(callback) {
|
|||||||
}, function(err) {
|
}, function(err) {
|
||||||
|
|
||||||
if (err || !block) {
|
if (err || !block) {
|
||||||
return callback(err ||
|
log.error(err ||
|
||||||
new Error('Block Service: none of the blocks from the headers match what is already indexed in the block service.'));
|
'Block Service: none of the blocks from the headers match what is already indexed in the block service.'); return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
self._setTip({ hash: block.rhash(), height: height + 1 }, callback);
|
self._setTip({ hash: block.rhash(), height: height + 1 }, callback);
|
||||||
@ -370,8 +377,8 @@ BlockService.prototype._loadRecentBlockHashes = function(callback) {
|
|||||||
self.getBlock(hash, function(err, block) {
|
self.getBlock(hash, function(err, block) {
|
||||||
|
|
||||||
if (err || !block) {
|
if (err || !block) {
|
||||||
return callback(err || new Error('Block Service: attempted to retrieve block: ' + hash +
|
log.error(err || 'Block Service: attempted to retrieve block: ' + hash +
|
||||||
' but was not in the index.'));
|
' but was not in the index.'); return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
var prevHash = bcoin.util.revHex(block.prevBlock);
|
var prevHash = bcoin.util.revHex(block.prevBlock);
|
||||||
@ -387,7 +394,11 @@ BlockService.prototype._loadRecentBlockHashes = function(callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(self._recentBlockHashes.length === times, 'Block Service: did not load enough recent block hashes from the index.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (self._recentBlockHashes.length != times) {
|
||||||
|
log.error('Block Service: did not load enough recent block hashes from the index.');
|
||||||
|
}
|
||||||
|
//assert(self._recentBlockHashes.length === times, 'Block Service: did not load enough recent block hashes from the index.');
|
||||||
log.info('Block Service: loaded: ' + self._recentBlockHashes.length + ' hashes from the index.');
|
log.info('Block Service: loaded: ' + self._recentBlockHashes.length + ' hashes from the index.');
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
@ -406,7 +417,7 @@ BlockService.prototype._getTimeSinceLastBlock = function(callback) {
|
|||||||
self._header.getBlockHeader(Math.max(self._tip.height - 1, 0), function(err, header) {
|
self._header.getBlockHeader(Math.max(self._tip.height - 1, 0), function(err, header) {
|
||||||
|
|
||||||
if(err || !header) {
|
if(err || !header) {
|
||||||
return callback(err || new Error('Block Service: we should have a header in order to get time since last block.'));
|
log.error(err || 'Block Service: we should have a header in order to get time since last block.'); return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
async.map([ self._tip.hash, header.hash ], function(hash, next) {
|
async.map([ self._tip.hash, header.hash ], function(hash, next) {
|
||||||
@ -628,6 +639,7 @@ BlockService.prototype._startBlockSubscription = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._subscribedBlock = true;
|
this._subscribedBlock = true;
|
||||||
|
this._ignoredBlockCount = 0; //SZ: reset the ignored count to 0 when subscription starts
|
||||||
|
|
||||||
log.info('Block Service: starting p2p block subscription.');
|
log.info('Block Service: starting p2p block subscription.');
|
||||||
this._bus.on('p2p/block', this._queueBlock.bind(this));
|
this._bus.on('p2p/block', this._queueBlock.bind(this));
|
||||||
@ -656,7 +668,7 @@ BlockService.prototype._findLatestValidBlockHeader = function(callback) {
|
|||||||
if (self._reorgToBlock) {
|
if (self._reorgToBlock) {
|
||||||
return self._header.getBlockHeader(self._reorgToBlock, function(err, header) {
|
return self._header.getBlockHeader(self._reorgToBlock, function(err, header) {
|
||||||
if (err || !header) {
|
if (err || !header) {
|
||||||
return callback(err || new Error('Block Service: header not found to reorg to.'));
|
log.error(err || 'Block Service: header not found to reorg to.'); return callback(err);
|
||||||
}
|
}
|
||||||
callback(null, header);
|
callback(null, header);
|
||||||
});
|
});
|
||||||
@ -711,12 +723,19 @@ BlockService.prototype._findLatestValidBlockHeader = function(callback) {
|
|||||||
// any of our recent block hashes in its indexes.
|
// any of our recent block hashes in its indexes.
|
||||||
// if some joker mines a block using an orphan block as its prev block, then the effect of this will be
|
// if some joker mines a block using an orphan block as its prev block, then the effect of this will be
|
||||||
// us detecting a reorg, but not actually reorging anything
|
// us detecting a reorg, but not actually reorging anything
|
||||||
assert(header, 'Block Service: we could not locate any of our recent block hashes in the header service ' +
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
'index. Perhaps our header service sync\'ed to the wrong chain?');
|
if (!_.isUndefined(header)) {
|
||||||
|
if (header == false) {
|
||||||
assert(header.height <= self._tip.height, 'Block Service: we found a common ancestor header whose ' +
|
log.error('Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?');
|
||||||
'height was greater than our current tip. This should be impossible.');
|
}
|
||||||
|
}
|
||||||
|
// assert(header, 'Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?');
|
||||||
|
if (!_.isUndefined(header.height)) {
|
||||||
|
if (header.height > self._tip.height) {
|
||||||
|
log.error('Block Service: we found a common ancestor header whose ' + 'height was greater than our current tip. This should be impossible.');
|
||||||
|
}
|
||||||
|
// assert(header.height <= self._tip.height, 'Block Service: we found a common ancestor header whose ' + 'height was greater than our current tip. This should be impossible.');
|
||||||
|
}
|
||||||
callback(null, header);
|
callback(null, header);
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -739,13 +758,13 @@ BlockService.prototype._findBlocksToRemove = function(commonHeader, callback) {
|
|||||||
self._getBlock(hash, function(err, block) {
|
self._getBlock(hash, function(err, block) {
|
||||||
|
|
||||||
if (err || !block) {
|
if (err || !block) {
|
||||||
return next(err || new Error('Block Service: block not found in index.'));
|
return next(err || 'Block Service: block not found in index.');
|
||||||
}
|
}
|
||||||
|
|
||||||
self._timestamp.getTimestamp(block.rhash(), function(err, timestamp) {
|
self._timestamp.getTimestamp(block.rhash(), function(err, timestamp) {
|
||||||
|
|
||||||
if (err || !timestamp) {
|
if (err || !timestamp) {
|
||||||
return callback(err || new Error('timestamp missing from reorg.'));
|
log.error(err || 'timestamp missing from reorg.'); return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.__height = height;
|
block.__height = height;
|
||||||
@ -815,8 +834,10 @@ BlockService.prototype._handleReorg = function(callback) {
|
|||||||
|
|
||||||
blocksToRemove = _blocksToRemove;
|
blocksToRemove = _blocksToRemove;
|
||||||
|
|
||||||
assert(blocksToRemove.length >= 1 && blocksToRemove.length <= self._recentBlockHashes.length,
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
'Block Service: the number of blocks to remove looks to be incorrect.');
|
if (blocksToRemove.length < 1 || blocksToRemove.length > self._recentBlockHashes.length) {
|
||||||
|
log.error('Block Service: the number of blocks to remove looks to be incorrect.'); }
|
||||||
|
// assert(blocksToRemove.length >= 1 && blocksToRemove.length <= self._recentBlockHashes.length, 'Block Service: the number of blocks to remove looks to be incorrect.');
|
||||||
|
|
||||||
log.warn('Block Service: chain reorganization detected, current height/hash: ' + self._tip.height + '/' +
|
log.warn('Block Service: chain reorganization detected, current height/hash: ' + self._tip.height + '/' +
|
||||||
self._tip.hash + ' common ancestor hash: ' + commonAncestorHeader.hash + ' at height: ' + commonAncestorHeader.height +
|
self._tip.hash + ' common ancestor hash: ' + commonAncestorHeader.hash + ' at height: ' + commonAncestorHeader.height +
|
||||||
@ -920,6 +941,15 @@ BlockService.prototype._processBlock = function(block, callback) {
|
|||||||
return self._saveBlock(block, callback);
|
return self._saveBlock(block, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SZ: count the ignored blocks. if many blocks ignored, trigger sync process
|
||||||
|
if(self._ignoredBlockCount < MAX_IGNORED_BLOCK)
|
||||||
|
self._ignoredBlockCount++;
|
||||||
|
else {
|
||||||
|
self._ignoredBlockCount = 0;
|
||||||
|
self._removeAllSubscriptions();
|
||||||
|
self._startSync();
|
||||||
|
}
|
||||||
|
|
||||||
// reorg -- in this case, we will not handle the reorg right away
|
// reorg -- in this case, we will not handle the reorg right away
|
||||||
// instead, we will skip the block and wait for the eventual call to
|
// instead, we will skip the block and wait for the eventual call to
|
||||||
// "onHeaders" function. When the header service calls this function,
|
// "onHeaders" function. When the header service calls this function,
|
||||||
@ -935,6 +965,7 @@ BlockService.prototype._saveBlock = function(block, callback) {
|
|||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
block.__height = self._tip.height + 1;
|
block.__height = self._tip.height + 1;
|
||||||
|
self._ignoredBlockCount = 0; //SZ: a block is saved, reset the ignored count
|
||||||
|
|
||||||
var services = self.node.services;
|
var services = self.node.services;
|
||||||
|
|
||||||
@ -1079,7 +1110,7 @@ BlockService.prototype._startSync = function() {
|
|||||||
this.on('next block', this._sync.bind(this));
|
this.on('next block', this._sync.bind(this));
|
||||||
this.on('synced', this._onSynced.bind(this));
|
this.on('synced', this._onSynced.bind(this));
|
||||||
clearInterval(this._reportInterval);
|
clearInterval(this._reportInterval);
|
||||||
this._reportingInterval = setInterval(this._logProgress.bind(this), 5000);
|
this._reportInterval = setInterval(this._logProgress.bind(this), 5000);
|
||||||
return this._sync();
|
return this._sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -315,7 +315,7 @@ Reorg.prototype.findCommonAncestorAndNewHashes = function(oldTipHash, newTipHash
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!mainPosition && !forkPosition) {
|
if(!mainPosition && !forkPosition) {
|
||||||
return next(new Error('Unknown common ancestor'));
|
return next('Unknown common ancestor');
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
var util = require('util');
|
var util = require('util');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
var _ = require('lodash');
|
||||||
var levelup = require('levelup');
|
var levelup = require('levelup');
|
||||||
var leveldown = require('leveldown');
|
var leveldown = require('leveldown');
|
||||||
var mkdirp = require('mkdirp');
|
var mkdirp = require('mkdirp');
|
||||||
@ -50,7 +51,6 @@ DB.prototype._onError = function(err) {
|
|||||||
if (!this._stopping) {
|
if (!this._stopping) {
|
||||||
log.error('Db Service: error: ' + err);
|
log.error('Db Service: error: ' + err);
|
||||||
//FLO Crash Error Resolution by RanchiMall 10th May 2021
|
//FLO Crash Error Resolution by RanchiMall 10th May 2021
|
||||||
//return this.node.stop();
|
|
||||||
//this.node.stop();
|
//this.node.stop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -69,9 +69,9 @@ DB.prototype._setDataPath = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype._setVersion = function(callback) {
|
DB.prototype._setVersion = function(callback) {
|
||||||
var versionBuffer = Buffer.from(new Array(4));
|
var versionBuffer = new Buffer(new Array(4));
|
||||||
versionBuffer.writeUInt32BE(this.version);
|
versionBuffer.writeUInt32BE(this.version);
|
||||||
this.put(Buffer.concat([ this._dbPrefix, Buffer.from('version', 'utf8') ]), versionBuffer, callback);
|
this.put(Buffer.concat([ this._dbPrefix, new Buffer('version', 'utf8') ]), versionBuffer, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
DB.prototype.start = function(callback) {
|
DB.prototype.start = function(callback) {
|
||||||
@ -96,7 +96,7 @@ DB.prototype.get = function(key, options, callback) {
|
|||||||
var cb = callback;
|
var cb = callback;
|
||||||
var opts = options;
|
var opts = options;
|
||||||
|
|
||||||
if (typeof callback !== 'function') {
|
if (!_.isFunction(callback)) {
|
||||||
cb = options;
|
cb = options;
|
||||||
opts = {};
|
opts = {};
|
||||||
}
|
}
|
||||||
@ -119,7 +119,9 @@ DB.prototype.get = function(key, options, callback) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
cb(new Error('Shutdown sequence underway, not able to complete the query'));
|
// FLOSight Error Correction from RanchiMall 20th May 2021.
|
||||||
|
//cb(new Error('Shutdown sequence underway, not able to complete the query'));
|
||||||
|
log.error('Shutdown sequence underway, not able to complete the query');
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -130,17 +132,40 @@ DB.prototype.put = function(key, value, callback) {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Buffer.isBuffer(key), 'key NOT a buffer as expected.');
|
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (Buffer.isBuffer(key) == false) {
|
||||||
|
log.error('key NOT a buffer as expected.');
|
||||||
|
}
|
||||||
|
// assert(Buffer.isBuffer(key), 'key NOT a buffer as expected.');
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
|
||||||
assert(Buffer.isBuffer(value), 'value exists but NOT a buffer as expected.');
|
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (Buffer.isBuffer(value) == false) {
|
||||||
|
log.error('value exists but NOT a buffer as expected.');
|
||||||
|
}
|
||||||
|
//assert(Buffer.isBuffer(value), 'value exists but NOT a buffer as expected.');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._store.put(key, value, callback);
|
this._store.put(key, value, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DB.prototype.del = function(key, callback) {
|
||||||
|
|
||||||
|
if (this._stopping) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (Buffer.isBuffer(key) == false) {
|
||||||
|
log.error('key NOT a buffer as expected.');
|
||||||
|
}
|
||||||
|
// assert(Buffer.isBuffer(key), 'key NOT a buffer as expected.');
|
||||||
|
|
||||||
|
this._store.del(key, callback);
|
||||||
|
}
|
||||||
|
|
||||||
DB.prototype.batch = function(ops, callback) {
|
DB.prototype.batch = function(ops, callback) {
|
||||||
|
|
||||||
if (this._stopping) {
|
if (this._stopping) {
|
||||||
@ -149,11 +174,18 @@ DB.prototype.batch = function(ops, callback) {
|
|||||||
|
|
||||||
for(var i = 0; i < ops.length; i++) {
|
for(var i = 0; i < ops.length; i++) {
|
||||||
|
|
||||||
assert(Buffer.isBuffer(ops[i].key), 'key NOT a buffer as expected.');
|
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (Buffer.isBuffer(ops[i].key) == false) {
|
||||||
|
log.error('key NOT a buffer as expected.');
|
||||||
|
}
|
||||||
|
//assert(Buffer.isBuffer(ops[i].key), 'key NOT a buffer as expected.');
|
||||||
|
|
||||||
if (ops[i].value) {
|
if (ops[i].value) {
|
||||||
|
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
assert(Buffer.isBuffer(ops[i].value), 'value exists but NOT a buffer as expected.');
|
if (Buffer.isBuffer(ops[i].value) == false) {
|
||||||
|
log.error('value exists but NOT a buffer as expected.');
|
||||||
|
}
|
||||||
|
//assert(Buffer.isBuffer(ops[i].value), 'value exists but NOT a buffer as expected.');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -207,7 +239,7 @@ DB.prototype.getPublishEvents = function() {
|
|||||||
|
|
||||||
DB.prototype.getServiceTip = function(serviceName, callback) {
|
DB.prototype.getServiceTip = function(serviceName, callback) {
|
||||||
|
|
||||||
var keyBuf = Buffer.concat([ this._dbPrefix, Buffer.from('tip-' + serviceName, 'utf8') ]);
|
var keyBuf = Buffer.concat([ this._dbPrefix, new Buffer('tip-' + serviceName, 'utf8') ]);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
self.get(keyBuf, function(err, tipBuf) {
|
self.get(keyBuf, function(err, tipBuf) {
|
||||||
@ -242,8 +274,8 @@ DB.prototype.getServiceTip = function(serviceName, callback) {
|
|||||||
DB.prototype.getPrefix = function(service, callback) {
|
DB.prototype.getPrefix = function(service, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var keyBuf = Buffer.concat([ self._dbPrefix, Buffer.from('prefix-', 'utf8'), Buffer.from(service, 'utf8') ]);
|
var keyBuf = Buffer.concat([ self._dbPrefix, new Buffer('prefix-', 'utf8'), new Buffer(service, 'utf8') ]);
|
||||||
var unusedBuf = Buffer.concat([ self._dbPrefix, Buffer.from('nextUnused', 'utf8') ]);
|
var unusedBuf = Buffer.concat([ self._dbPrefix, new Buffer('nextUnused', 'utf8') ]);
|
||||||
|
|
||||||
function getPrefix(next) {
|
function getPrefix(next) {
|
||||||
|
|
||||||
@ -270,7 +302,7 @@ DB.prototype.getPrefix = function(service, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!buffer) {
|
if(!buffer) {
|
||||||
return next(null, Buffer.from('0001', 'hex'));
|
return next(null, new Buffer('0001', 'hex'));
|
||||||
}
|
}
|
||||||
|
|
||||||
next(null, buffer);
|
next(null, buffer);
|
||||||
@ -294,7 +326,7 @@ DB.prototype.getPrefix = function(service, callback) {
|
|||||||
function putUnused(buffer, next) {
|
function putUnused(buffer, next) {
|
||||||
|
|
||||||
var prefix = buffer.readUInt16BE();
|
var prefix = buffer.readUInt16BE();
|
||||||
var nextUnused = Buffer.alloc(2);
|
var nextUnused = new Buffer(2);
|
||||||
nextUnused.writeUInt16BE(prefix + 1);
|
nextUnused.writeUInt16BE(prefix + 1);
|
||||||
|
|
||||||
self.put(unusedBuf, nextUnused, function(err) {
|
self.put(unusedBuf, nextUnused, function(err) {
|
||||||
|
|||||||
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this._servicePrefix = servicePrefix;
|
this._servicePrefix = servicePrefix;
|
||||||
this._hashPrefix = Buffer.from('00', 'hex');
|
this._hashPrefix = new Buffer('00', 'hex');
|
||||||
this._heightPrefix = Buffer.from('01', 'hex');
|
this._heightPrefix = new Buffer('01', 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- hash --> header
|
// ---- hash --> header
|
||||||
Encoding.prototype.encodeHeaderHashKey = function(hash) {
|
Encoding.prototype.encodeHeaderHashKey = function(hash) {
|
||||||
var hashBuf = Buffer.from(hash, 'hex');
|
var hashBuf = new Buffer(hash, 'hex');
|
||||||
return Buffer.concat([ this._servicePrefix, this._hashPrefix, hashBuf ]);
|
return Buffer.concat([ this._servicePrefix, this._hashPrefix, hashBuf ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ Encoding.prototype.decodeHeaderHashKey = function(buffer) {
|
|||||||
|
|
||||||
// ---- height --> header
|
// ---- height --> header
|
||||||
Encoding.prototype.encodeHeaderHeightKey = function(height) {
|
Encoding.prototype.encodeHeaderHeightKey = function(height) {
|
||||||
var heightBuf = Buffer.alloc(4);
|
var heightBuf = new Buffer(4);
|
||||||
heightBuf.writeUInt32BE(height);
|
heightBuf.writeUInt32BE(height);
|
||||||
return Buffer.concat([ this._servicePrefix, this._heightPrefix, heightBuf ]);
|
return Buffer.concat([ this._servicePrefix, this._heightPrefix, heightBuf ]);
|
||||||
};
|
};
|
||||||
@ -29,21 +29,21 @@ Encoding.prototype.decodeHeaderHeightKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeHeaderValue = function(header) {
|
Encoding.prototype.encodeHeaderValue = function(header) {
|
||||||
var hashBuf = Buffer.from(header.hash, 'hex');
|
var hashBuf = new Buffer(header.hash, 'hex');
|
||||||
var versionBuf = Buffer.alloc(4);
|
var versionBuf = new Buffer(4);
|
||||||
versionBuf.writeInt32BE(header.version);
|
versionBuf.writeInt32BE(header.version);
|
||||||
var prevHash = Buffer.from(header.prevHash, 'hex');
|
var prevHash = new Buffer(header.prevHash, 'hex');
|
||||||
var merkleRoot = Buffer.from(header.merkleRoot, 'hex');
|
var merkleRoot = new Buffer(header.merkleRoot, 'hex');
|
||||||
var tsBuf = Buffer.alloc(4);
|
var tsBuf = new Buffer(4);
|
||||||
tsBuf.writeUInt32BE(header.timestamp || header.time);
|
tsBuf.writeUInt32BE(header.timestamp || header.time);
|
||||||
var bitsBuf = Buffer.alloc(4);
|
var bitsBuf = new Buffer(4);
|
||||||
bitsBuf.writeUInt32BE(header.bits);
|
bitsBuf.writeUInt32BE(header.bits);
|
||||||
var nonceBuf = Buffer.alloc(4);
|
var nonceBuf = new Buffer(4);
|
||||||
nonceBuf.writeUInt32BE(header.nonce);
|
nonceBuf.writeUInt32BE(header.nonce);
|
||||||
var heightBuf = Buffer.alloc(4);
|
var heightBuf = new Buffer(4);
|
||||||
heightBuf.writeUInt32BE(header.height);
|
heightBuf.writeUInt32BE(header.height);
|
||||||
var chainworkBuf = Buffer.from(header.chainwork, 'hex');
|
var chainworkBuf = new Buffer(header.chainwork, 'hex');
|
||||||
var nextHash = Buffer.from(header.nextHash || new Array(65).join('0'), 'hex');
|
var nextHash = new Buffer(header.nextHash || new Array(65).join('0'), 'hex');
|
||||||
return Buffer.concat([
|
return Buffer.concat([
|
||||||
hashBuf,
|
hashBuf,
|
||||||
versionBuf,
|
versionBuf,
|
||||||
|
|||||||
@ -14,6 +14,8 @@ var assert = require('assert');
|
|||||||
var constants = require('../../constants');
|
var constants = require('../../constants');
|
||||||
var bcoin = require('fcoin');
|
var bcoin = require('fcoin');
|
||||||
|
|
||||||
|
const SYNC_CHECK_INTERVAL = 1000 * 60 * 15; //15 mins
|
||||||
|
|
||||||
var HeaderService = function(options) {
|
var HeaderService = function(options) {
|
||||||
|
|
||||||
BaseService.call(this, options);
|
BaseService.call(this, options);
|
||||||
@ -145,7 +147,11 @@ HeaderService.prototype._adjustTipBackToCheckpoint = function() {
|
|||||||
|
|
||||||
HeaderService.prototype._setGenesisBlock = function(callback) {
|
HeaderService.prototype._setGenesisBlock = function(callback) {
|
||||||
|
|
||||||
assert(this._tip.hash === this.GENESIS_HASH, 'Expected tip hash to be genesis hash, but it was not.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (this._tip.hash != this.GENESIS_HASH) {
|
||||||
|
log.error('Expected tip hash to be genesis hash, but it was not.');
|
||||||
|
}
|
||||||
|
// assert(this._tip.hash === this.GENESIS_HASH, 'Expected tip hash to be genesis hash, but it was not.');
|
||||||
|
|
||||||
var genesisHeader = {
|
var genesisHeader = {
|
||||||
hash: this.GENESIS_HASH,
|
hash: this.GENESIS_HASH,
|
||||||
@ -412,7 +418,10 @@ HeaderService.prototype._getDBOpForLastHeader = function(nextHeader) {
|
|||||||
this._lastHeader.nextHash = nextHeader.hash;
|
this._lastHeader.nextHash = nextHeader.hash;
|
||||||
var keyHash = this._encoding.encodeHeaderHashKey(this._lastHeader.hash);
|
var keyHash = this._encoding.encodeHeaderHashKey(this._lastHeader.hash);
|
||||||
|
|
||||||
assert(this._lastHeader.height >= 0, 'Trying to save a header with incorrect height.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (this._lastHeader.height < 0) { log.error('Trying to save a header with incorrect height.');
|
||||||
|
}
|
||||||
|
// assert(this._lastHeader.height >= 0, 'Trying to save a header with incorrect height.');
|
||||||
|
|
||||||
var keyHeight = this._encoding.encodeHeaderHeightKey(this._lastHeader.height);
|
var keyHeight = this._encoding.encodeHeaderHeightKey(this._lastHeader.height);
|
||||||
var value = this._encoding.encodeHeaderValue(this._lastHeader);
|
var value = this._encoding.encodeHeaderValue(this._lastHeader);
|
||||||
@ -467,8 +476,11 @@ HeaderService.prototype._onHeaders = function(headers) {
|
|||||||
|
|
||||||
var header = transformedHeaders[i];
|
var header = transformedHeaders[i];
|
||||||
|
|
||||||
assert(self._lastHeader.hash === header.prevHash, 'headers not in order: ' + self._lastHeader.hash +
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
' -and- ' + header.prevHash + ' Last header at height: ' + self._lastHeader.height);
|
if (self._lastHeader.hash != header.prevHash) {
|
||||||
|
log.error('headers not in order: ' + self._lastHeader.hash + ' -and- ' + header.prevHash + ' Last header at height: ' + self._lastHeader.height);
|
||||||
|
}
|
||||||
|
// assert(self._lastHeader.hash === header.prevHash, 'headers not in order: ' + self._lastHeader.hash + ' -and- ' + header.prevHash + ' Last header at height: ' + self._lastHeader.height);
|
||||||
|
|
||||||
var ops = self._onHeader(header);
|
var ops = self._onHeader(header);
|
||||||
|
|
||||||
@ -485,9 +497,9 @@ HeaderService.prototype._onHeaders = function(headers) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HeaderService.prototype._handleError = function(err) {
|
HeaderService.prototype._handleError = function(err) {
|
||||||
log.error('Header Service: ' + err);
|
log.error('Error in Header Service: ' + err);
|
||||||
// FLO Crash Error Resolution by RanchiMall 10th May 2021
|
return;
|
||||||
// this.node.stop();
|
//this.node.stop();
|
||||||
};
|
};
|
||||||
|
|
||||||
HeaderService.prototype._saveHeaders = function(dbOps, callback) {
|
HeaderService.prototype._saveHeaders = function(dbOps, callback) {
|
||||||
@ -512,6 +524,7 @@ HeaderService.prototype._saveHeaders = function(dbOps, callback) {
|
|||||||
HeaderService.prototype._onHeadersSave = function(callback) {
|
HeaderService.prototype._onHeadersSave = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
self._syncUnresponsive = false; //SZ: got response from peer
|
||||||
self._logProgress();
|
self._logProgress();
|
||||||
|
|
||||||
if (!self._syncComplete()) {
|
if (!self._syncComplete()) {
|
||||||
@ -519,6 +532,12 @@ HeaderService.prototype._onHeadersSave = function(callback) {
|
|||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SZ: clear the interval check as sync is completed
|
||||||
|
if(self._syncCheckInterval){
|
||||||
|
clearInterval(self._syncCheckInterval);
|
||||||
|
self._syncCheckInterval = null;
|
||||||
|
}
|
||||||
|
|
||||||
self._endHeaderSubscription(); // we don't need headers any more
|
self._endHeaderSubscription(); // we don't need headers any more
|
||||||
self._startBlockSubscription(); // we need new blocks coming tu us aynchronuously
|
self._startBlockSubscription(); // we need new blocks coming tu us aynchronuously
|
||||||
|
|
||||||
@ -598,7 +617,7 @@ HeaderService.prototype._getHeader = function(height, hash, callback) {
|
|||||||
/*jshint -W018 */
|
/*jshint -W018 */
|
||||||
if (!hash && !(height >= 0)) {
|
if (!hash && !(height >= 0)) {
|
||||||
/*jshint +W018 */
|
/*jshint +W018 */
|
||||||
return callback(new Error('invalid arguments'));
|
return callback('invalid arguments');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (height === self._lastHeader.height || hash === self._lastHeader.hash) {
|
if (height === self._lastHeader.height || hash === self._lastHeader.hash) {
|
||||||
@ -697,6 +716,23 @@ HeaderService.prototype._startSync = function() {
|
|||||||
// common case
|
// common case
|
||||||
if (numNeeded > 0) {
|
if (numNeeded > 0) {
|
||||||
log.info('Header Service: Gathering: ' + numNeeded + ' ' + 'header(s) from the peer-to-peer network.');
|
log.info('Header Service: Gathering: ' + numNeeded + ' ' + 'header(s) from the peer-to-peer network.');
|
||||||
|
|
||||||
|
//SZ: Adding interval check for sync with peer is responsive or not
|
||||||
|
//(only if fcoin is started by flocore)
|
||||||
|
if(self._p2p._bcoin){
|
||||||
|
self._syncUnresponsive = true;
|
||||||
|
self._syncCheckInterval = setInterval(() => {
|
||||||
|
//check the best height
|
||||||
|
if(self._bestHeight < self._p2p._bcoin._bcoin.pool.chain.height)
|
||||||
|
self._bestHeight = self._p2p._bcoin._bcoin.pool.chain.height;
|
||||||
|
//call sync again if unresponsive
|
||||||
|
if(self._syncUnresponsive)
|
||||||
|
self._sync();
|
||||||
|
else //reset unresponsive as true
|
||||||
|
self._syncUnresponsive = true;
|
||||||
|
}, SYNC_CHECK_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
return self._sync();
|
return self._sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -778,9 +814,11 @@ HeaderService.prototype._findReorgConditionInNewPeer = function(callback) {
|
|||||||
|
|
||||||
// nothing matched...
|
// nothing matched...
|
||||||
// at this point, we should wonder if we are connected to the wrong network
|
// at this point, we should wonder if we are connected to the wrong network
|
||||||
assert(true, 'We tried to find a common header between current set of headers ' +
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
'and the new peer\'s set of headers, but there were none. This should be impossible ' +
|
if (false) {
|
||||||
' if the new peer is using the same genesis block.');
|
log.error('We tried to find a common header between current set of headers ' + 'and the new peer\'s set of headers, but there were none. This should be impossible ' + ' if the new peer is using the same genesis block.');
|
||||||
|
}
|
||||||
|
// assert(true, 'We tried to find a common header between current set of headers ' +'and the new peer\'s set of headers, but there were none. This should be impossible ' +' if the new peer is using the same genesis block.');
|
||||||
});
|
});
|
||||||
|
|
||||||
self._getP2PHeaders(self.GENESIS_HASH);
|
self._getP2PHeaders(self.GENESIS_HASH);
|
||||||
@ -881,7 +919,11 @@ HeaderService.prototype._sync = function() {
|
|||||||
|
|
||||||
HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
||||||
|
|
||||||
assert(blockCount >= 1, 'Header Service: block count to getEndHash must be at least 1.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (blockCount < 1) {
|
||||||
|
log.error('Header Service: block count to getEndHash must be at least 1.');
|
||||||
|
}
|
||||||
|
// assert(blockCount >= 1, 'Header Service: block count to getEndHash must be at least 1.');
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -892,7 +934,7 @@ HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (numResultsNeeded <= 0) {
|
if (numResultsNeeded <= 0) {
|
||||||
return callback(new Error('Header Service: block service is mis-aligned '));
|
return callback('Header Service: block service is mis-aligned ');
|
||||||
}
|
}
|
||||||
|
|
||||||
var startingHeight = tip.height + 1;
|
var startingHeight = tip.height + 1;
|
||||||
@ -922,8 +964,11 @@ HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
|||||||
if (streamErr) {
|
if (streamErr) {
|
||||||
return streamErr;
|
return streamErr;
|
||||||
}
|
}
|
||||||
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
assert(results.length === numResultsNeeded, 'getEndHash returned incorrect number of results.');
|
if (results.length != numResultsNeeded) {
|
||||||
|
log.error('getEndHash returned incorrect number of results.');
|
||||||
|
}
|
||||||
|
// assert(results.length === numResultsNeeded, 'getEndHash returned incorrect number of results.');
|
||||||
|
|
||||||
var index = numResultsNeeded - 1;
|
var index = numResultsNeeded - 1;
|
||||||
var endHash = index <= 0 || !results[index] ? 0 : results[index];
|
var endHash = index <= 0 || !results[index] ? 0 : results[index];
|
||||||
@ -941,7 +986,11 @@ HeaderService.prototype.getEndHash = function(tip, blockCount, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
HeaderService.prototype.getLastHeader = function() {
|
HeaderService.prototype.getLastHeader = function() {
|
||||||
assert(this._lastHeader, 'Last header should be populated.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (this._lastHeader == false) {
|
||||||
|
log.error('Last header should be populated.'); return;
|
||||||
|
}
|
||||||
|
// assert(this._lastHeader, 'Last header should be populated.');
|
||||||
return this._lastHeader;
|
return this._lastHeader;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -999,7 +1048,13 @@ HeaderService.prototype._adjustHeadersForCheckPointTip = function(callback) {
|
|||||||
return streamErr;
|
return streamErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(self._lastHeader, 'The last synced header was not in the database.');
|
|
||||||
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (self._lastHeader == false) {
|
||||||
|
log.error('The last synced header was not in the database.');
|
||||||
|
}
|
||||||
|
//assert(self._lastHeader, 'The last synced header was not in the database.');
|
||||||
|
|
||||||
self._tip.hash = self._lastHeader.hash;
|
self._tip.hash = self._lastHeader.hash;
|
||||||
self._tip.height = self._lastHeader.height;
|
self._tip.height = self._lastHeader.height;
|
||||||
self._db.batch(removalOps, callback);
|
self._db.batch(removalOps, callback);
|
||||||
@ -1010,7 +1065,7 @@ HeaderService.prototype._adjustHeadersForCheckPointTip = function(callback) {
|
|||||||
|
|
||||||
HeaderService.prototype._getChainwork = function(header, prevHeader) {
|
HeaderService.prototype._getChainwork = function(header, prevHeader) {
|
||||||
|
|
||||||
var prevChainwork = new BN(Buffer.from(prevHeader.chainwork, 'hex'));
|
var prevChainwork = new BN(new Buffer(prevHeader.chainwork, 'hex'));
|
||||||
|
|
||||||
return this._computeChainwork(header.bits, prevChainwork);
|
return this._computeChainwork(header.bits, prevChainwork);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,13 +4,13 @@ var tx = require('fcoin').TX;
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this.servicePrefix = servicePrefix;
|
this.servicePrefix = servicePrefix;
|
||||||
this.txPrefix = Buffer.from('00', 'hex');
|
this.txPrefix = new Buffer('00', 'hex');
|
||||||
this.addressPrefix = Buffer.from('01', 'hex');
|
this.addressPrefix = new Buffer('01', 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
Encoding.prototype.encodeMempoolTransactionKey = function(txid) {
|
Encoding.prototype.encodeMempoolTransactionKey = function(txid) {
|
||||||
var buffers = [this.servicePrefix, this.txPrefix];
|
var buffers = [this.servicePrefix, this.txPrefix];
|
||||||
var txidBuffer = Buffer.from(txid, 'hex');
|
var txidBuffer = new Buffer(txid, 'hex');
|
||||||
buffers.push(txidBuffer);
|
buffers.push(txidBuffer);
|
||||||
return Buffer.concat(buffers);
|
return Buffer.concat(buffers);
|
||||||
};
|
};
|
||||||
@ -30,22 +30,22 @@ Encoding.prototype.decodeMempoolTransactionValue = function(buffer) {
|
|||||||
Encoding.prototype.encodeMempoolAddressKey = function(address, txid, index, input) {
|
Encoding.prototype.encodeMempoolAddressKey = function(address, txid, index, input) {
|
||||||
var buffers = [this.servicePrefix, this.addressPrefix];
|
var buffers = [this.servicePrefix, this.addressPrefix];
|
||||||
|
|
||||||
var addressSizeBuffer = Buffer.alloc(1);
|
var addressSizeBuffer = new Buffer(1);
|
||||||
addressSizeBuffer.writeUInt8(address.length);
|
addressSizeBuffer.writeUInt8(address.length);
|
||||||
var addressBuffer = Buffer.from(address, 'utf8');
|
var addressBuffer = new Buffer(address, 'utf8');
|
||||||
|
|
||||||
buffers.push(addressSizeBuffer);
|
buffers.push(addressSizeBuffer);
|
||||||
buffers.push(addressBuffer);
|
buffers.push(addressBuffer);
|
||||||
|
|
||||||
var txidBuffer = Buffer.from(txid || Array(65).join('0'), 'hex');
|
var txidBuffer = new Buffer(txid || Array(65).join('0'), 'hex');
|
||||||
buffers.push(txidBuffer);
|
buffers.push(txidBuffer);
|
||||||
|
|
||||||
var indexBuffer = Buffer.alloc(4);
|
var indexBuffer = new Buffer(4);
|
||||||
indexBuffer.writeUInt32BE(index || 0);
|
indexBuffer.writeUInt32BE(index || 0);
|
||||||
buffers.push(indexBuffer);
|
buffers.push(indexBuffer);
|
||||||
|
|
||||||
// this is whether the address appears in an input (1) or output (0)
|
// this is whether the address appears in an input (1) or output (0)
|
||||||
var inputBuffer = Buffer.alloc(1);
|
var inputBuffer = new Buffer(1);
|
||||||
inputBuffer.writeUInt8(input || 0);
|
inputBuffer.writeUInt8(input || 0);
|
||||||
buffers.push(inputBuffer);
|
buffers.push(inputBuffer);
|
||||||
|
|
||||||
|
|||||||
@ -283,7 +283,7 @@ MempoolService.prototype.getTxidsByAddress = function(address, type, callback) {
|
|||||||
var self = this;
|
var self = this;
|
||||||
var results = [];
|
var results = [];
|
||||||
var start = self._encoding.encodeMempoolAddressKey(address);
|
var start = self._encoding.encodeMempoolAddressKey(address);
|
||||||
var end = Buffer.concat([ start.slice(0, -37), Buffer.from(new Array(75).join('f'), 'hex') ]);
|
var end = Buffer.concat([ start.slice(0, -37), new Buffer(new Array(75).join('f'), 'hex') ]);
|
||||||
|
|
||||||
var criteria = {
|
var criteria = {
|
||||||
gte: start,
|
gte: start,
|
||||||
|
|||||||
@ -425,7 +425,12 @@ P2P.prototype._setListeners = function() {
|
|||||||
|
|
||||||
P2P.prototype._setResourceFilter = function(filter) {
|
P2P.prototype._setResourceFilter = function(filter) {
|
||||||
|
|
||||||
assert(filter && filter.startHash, 'A "startHash" field is required to retrieve headers or blocks');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (filter == false || filter.startHash == false) {
|
||||||
|
log.error('A "startHash" field is required to retrieve headers or blocks');
|
||||||
|
}
|
||||||
|
// assert(filter && filter.startHash, 'A "startHash" field is required to retrieve headers or blocks');
|
||||||
|
|
||||||
if (!filter.endHash) {
|
if (!filter.endHash) {
|
||||||
filter.endHash = 0;
|
filter.endHash = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this._servicePrefix = servicePrefix;
|
this._servicePrefix = servicePrefix;
|
||||||
this._blockPrefix = Buffer.from('00', 'hex');
|
this._blockPrefix = new Buffer('00', 'hex');
|
||||||
this._timestampPrefix = Buffer.from('01', 'hex');
|
this._timestampPrefix = new Buffer('01', 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- block hash -> timestamp
|
// ---- block hash -> timestamp
|
||||||
Encoding.prototype.encodeBlockTimestampKey = function(hash) {
|
Encoding.prototype.encodeBlockTimestampKey = function(hash) {
|
||||||
return Buffer.concat([this._servicePrefix, this._blockPrefix, Buffer.from(hash, 'hex')]);
|
return Buffer.concat([this._servicePrefix, this._blockPrefix, new Buffer(hash, 'hex')]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeBlockTimestampKey = function(buffer) {
|
Encoding.prototype.decodeBlockTimestampKey = function(buffer) {
|
||||||
@ -16,7 +16,7 @@ Encoding.prototype.decodeBlockTimestampKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeBlockTimestampValue = function(timestamp) {
|
Encoding.prototype.encodeBlockTimestampValue = function(timestamp) {
|
||||||
var timestampBuffer = Buffer.alloc(4);
|
var timestampBuffer = new Buffer(4);
|
||||||
timestampBuffer.writeUInt32BE(timestamp);
|
timestampBuffer.writeUInt32BE(timestamp);
|
||||||
return timestampBuffer;
|
return timestampBuffer;
|
||||||
};
|
};
|
||||||
@ -28,7 +28,7 @@ Encoding.prototype.decodeBlockTimestampValue = function(buffer) {
|
|||||||
|
|
||||||
// ---- timestamp -> block hash
|
// ---- timestamp -> block hash
|
||||||
Encoding.prototype.encodeTimestampBlockKey = function(timestamp) {
|
Encoding.prototype.encodeTimestampBlockKey = function(timestamp) {
|
||||||
var timestampBuffer = Buffer.alloc(4);
|
var timestampBuffer = new Buffer(4);
|
||||||
timestampBuffer.writeUInt32BE(timestamp);
|
timestampBuffer.writeUInt32BE(timestamp);
|
||||||
return Buffer.concat([this._servicePrefix, this._timestampPrefix, timestampBuffer]);
|
return Buffer.concat([this._servicePrefix, this._timestampPrefix, timestampBuffer]);
|
||||||
};
|
};
|
||||||
@ -38,7 +38,7 @@ Encoding.prototype.decodeTimestampBlockKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeTimestampBlockValue = function(hash) {
|
Encoding.prototype.encodeTimestampBlockValue = function(hash) {
|
||||||
return Buffer.from(hash, 'hex');
|
return new Buffer(hash, 'hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeTimestampBlockValue = function(buffer) {
|
Encoding.prototype.decodeTimestampBlockValue = function(buffer) {
|
||||||
|
|||||||
@ -4,13 +4,13 @@ var Tx = require('fcoin').TX;
|
|||||||
|
|
||||||
function Encoding(servicePrefix) {
|
function Encoding(servicePrefix) {
|
||||||
this.servicePrefix = servicePrefix;
|
this.servicePrefix = servicePrefix;
|
||||||
this.txIndex = Buffer.from('00', 'hex');
|
this.txIndex = new Buffer('00', 'hex');
|
||||||
this.spentIndex = Buffer.from('01', 'hex');
|
this.spentIndex = new Buffer('01', 'hex');
|
||||||
this.doubleSpentIndex = Buffer.from('02', 'hex');
|
this.doubleSpentIndex = new Buffer('02', 'hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
Encoding.prototype.encodeTransactionKey = function(txid) {
|
Encoding.prototype.encodeTransactionKey = function(txid) {
|
||||||
return Buffer.concat([this.servicePrefix, this.txIndex, Buffer.from(txid, 'hex')]);
|
return Buffer.concat([this.servicePrefix, this.txIndex, new Buffer(txid, 'hex')]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeTransactionKey = function(buffer) {
|
Encoding.prototype.decodeTransactionKey = function(buffer) {
|
||||||
@ -18,24 +18,24 @@ Encoding.prototype.decodeTransactionKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeTransactionValue = function(transaction) {
|
Encoding.prototype.encodeTransactionValue = function(transaction) {
|
||||||
var heightBuffer = Buffer.alloc(4);
|
var heightBuffer = new Buffer(4);
|
||||||
heightBuffer.writeUInt32BE(transaction.__height);
|
heightBuffer.writeUInt32BE(transaction.__height);
|
||||||
|
|
||||||
var hashBuffer = Buffer.from(transaction.__blockhash, 'hex');
|
var hashBuffer = new Buffer(transaction.__blockhash, 'hex');
|
||||||
|
|
||||||
var timestampBuffer = Buffer.alloc(4);
|
var timestampBuffer = new Buffer(4);
|
||||||
timestampBuffer.writeUInt32BE(transaction.__timestamp);
|
timestampBuffer.writeUInt32BE(transaction.__timestamp);
|
||||||
|
|
||||||
var inputValues = transaction.__inputValues;
|
var inputValues = transaction.__inputValues;
|
||||||
var inputValuesBuffer = Buffer.alloc(8 * inputValues.length);
|
var inputValuesBuffer = new Buffer(8 * inputValues.length);
|
||||||
for(var i = 0; i < inputValues.length; i++) {
|
for(var i = 0; i < inputValues.length; i++) {
|
||||||
inputValuesBuffer.writeDoubleBE(inputValues[i], i * 8);
|
inputValuesBuffer.writeDoubleBE(inputValues[i], i * 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
var inputValuesLengthBuffer = Buffer.alloc(2);
|
var inputValuesLengthBuffer = new Buffer(2);
|
||||||
inputValuesLengthBuffer.writeUInt16BE(inputValues.length);
|
inputValuesLengthBuffer.writeUInt16BE(inputValues.length);
|
||||||
|
|
||||||
return Buffer.concat([heightBuffer, hashBuffer, timestampBuffer,
|
return new Buffer.concat([heightBuffer, hashBuffer, timestampBuffer,
|
||||||
inputValuesLengthBuffer, inputValuesBuffer, transaction.toRaw()]);
|
inputValuesLengthBuffer, inputValuesBuffer, transaction.toRaw()]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -65,9 +65,9 @@ Encoding.prototype.decodeTransactionValue = function(buffer) {
|
|||||||
|
|
||||||
// for every input we receive, we make an entry for what output it spends
|
// for every input we receive, we make an entry for what output it spends
|
||||||
Encoding.prototype.encodeSpentKey = function(txid, outputIndex) {
|
Encoding.prototype.encodeSpentKey = function(txid, outputIndex) {
|
||||||
var outputIndexBuffer = Buffer.alloc(4);
|
var outputIndexBuffer = new Buffer(4);
|
||||||
outputIndexBuffer.writeUInt32BE(outputIndex);
|
outputIndexBuffer.writeUInt32BE(outputIndex);
|
||||||
return Buffer.concat([this.servicePrefix, this.spentIndex, Buffer.from(txid, 'hex'), outputIndexBuffer]);
|
return Buffer.concat([this.servicePrefix, this.spentIndex, new Buffer(txid, 'hex'), outputIndexBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeSpentKey = function(buffer) {
|
Encoding.prototype.decodeSpentKey = function(buffer) {
|
||||||
@ -80,12 +80,12 @@ Encoding.prototype.decodeSpentKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeSpentValue = function(txid, inputIndex, blockHeight, blockHash) {
|
Encoding.prototype.encodeSpentValue = function(txid, inputIndex, blockHeight, blockHash) {
|
||||||
var inputIndexBuffer = Buffer.alloc(4);
|
var inputIndexBuffer = new Buffer(4);
|
||||||
inputIndexBuffer.writeUInt32BE(inputIndex);
|
inputIndexBuffer.writeUInt32BE(inputIndex);
|
||||||
var blockHeightBuffer = Buffer.alloc(4);
|
var blockHeightBuffer = new Buffer(4);
|
||||||
blockHeightBuffer.writeUInt32BE(blockHeight);
|
blockHeightBuffer.writeUInt32BE(blockHeight);
|
||||||
var blockHashBuffer = Buffer.from(blockHash, 'hex');
|
var blockHashBuffer = new Buffer(blockHash, 'hex');
|
||||||
return Buffer.concat([Buffer.from(txid, 'hex'), inputIndexBuffer, blockHeightBuffer, blockHashBuffer]);
|
return Buffer.concat([new Buffer(txid, 'hex'), inputIndexBuffer, blockHeightBuffer, blockHashBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeSpentValue = function(buffer) {
|
Encoding.prototype.decodeSpentValue = function(buffer) {
|
||||||
@ -102,9 +102,9 @@ Encoding.prototype.decodeSpentValue = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeDoubleSpentKey = function(txid, outputIndex) {
|
Encoding.prototype.encodeDoubleSpentKey = function(txid, outputIndex) {
|
||||||
var outputIndexBuffer = Buffer.alloc(4);
|
var outputIndexBuffer = new Buffer(4);
|
||||||
outputIndexBuffer.writeUInt32BE(outputIndex);
|
outputIndexBuffer.writeUInt32BE(outputIndex);
|
||||||
return Buffer.concat([this.servicePrefix, this.spentIndex, Buffer.from(txid, 'hex'), outputIndexBuffer]);
|
return Buffer.concat([this.servicePrefix, this.spentIndex, new Buffer(txid, 'hex'), outputIndexBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeDoubleSpentKey = function(buffer) {
|
Encoding.prototype.decodeDoubleSpentKey = function(buffer) {
|
||||||
@ -117,12 +117,12 @@ Encoding.prototype.decodeDoubleSpentKey = function(buffer) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.encodeDoubleSpentValue = function(txid, inputIndex, blockHeight, blockHash) {
|
Encoding.prototype.encodeDoubleSpentValue = function(txid, inputIndex, blockHeight, blockHash) {
|
||||||
var inputIndexBuffer = Buffer.alloc(4);
|
var inputIndexBuffer = new Buffer(4);
|
||||||
inputIndexBuffer.writeUInt32BE(inputIndex);
|
inputIndexBuffer.writeUInt32BE(inputIndex);
|
||||||
var blockHeightBuffer = Buffer.alloc(4);
|
var blockHeightBuffer = new Buffer(4);
|
||||||
blockHeightBuffer.writeUInt32BE(inputIndex);
|
blockHeightBuffer.writeUInt32BE(inputIndex);
|
||||||
var blockHashBuffer = Buffer.from(blockHash, 'hex');
|
var blockHashBuffer = new Buffer(blockHash, 'hex');
|
||||||
return Buffer.concat([Buffer.from(txid, 'hex'), inputIndexBuffer, blockHeightBuffer, blockHashBuffer]);
|
return Buffer.concat([new Buffer(txid, 'hex'), inputIndexBuffer, blockHeightBuffer, blockHashBuffer]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Encoding.prototype.decodeDoubleSpentValue = function(buffer) {
|
Encoding.prototype.decodeDoubleSpentValue = function(buffer) {
|
||||||
|
|||||||
@ -7,6 +7,7 @@ var _ = require('lodash');
|
|||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var LRU = require('lru-cache');
|
var LRU = require('lru-cache');
|
||||||
|
var log = require('../../index').log;
|
||||||
|
|
||||||
function TransactionService(options) {
|
function TransactionService(options) {
|
||||||
BaseService.call(this, options);
|
BaseService.call(this, options);
|
||||||
@ -113,7 +114,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
|||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
if (typeof callback !== 'function') {
|
if (!_.isFunction(callback)) {
|
||||||
callback = options;
|
callback = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,8 +185,11 @@ TransactionService.prototype.setTxMetaInfo = function(tx, options, callback) {
|
|||||||
|
|
||||||
var inputSatoshis = 0;
|
var inputSatoshis = 0;
|
||||||
|
|
||||||
assert(tx.__inputValues.length === tx.inputs.length,
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
'Transaction Service: input values length is not the same as the number of inputs.');
|
if (tx.__inputValues.length != tx.inputs.length) {
|
||||||
|
log.error('Transaction Service: input values length is not the same as the number of inputs.');
|
||||||
|
}
|
||||||
|
// assert(tx.__inputValues.length === tx.inputs.length, 'Transaction Service: input values length is not the same as the number of inputs.');
|
||||||
|
|
||||||
tx.__inputValues.forEach(function(val) {
|
tx.__inputValues.forEach(function(val) {
|
||||||
|
|
||||||
@ -308,14 +312,18 @@ TransactionService.prototype._getInputValues = function(tx, options, callback) {
|
|||||||
// if not in mempool or tx index, we just don't have it, yet?
|
// if not in mempool or tx index, we just don't have it, yet?
|
||||||
function(txid, tx, next) {
|
function(txid, tx, next) {
|
||||||
if (!tx) {
|
if (!tx) {
|
||||||
return next(new Error('Transaction Service: prev transacion: (' + input.prevout.txid() + ') for tx: ' +
|
return next(log.error('Transaction Service: prev transacion: (' + input.prevout.txid() + ') for tx: ' +
|
||||||
_tx.txid() + ' at input index: ' + outputIndex + ' is missing from the index or not in the memory pool. It could be' +
|
_tx.txid() + ' at input index: ' + outputIndex + ' is missing from the index or not in the memory pool. It could be' +
|
||||||
' that the parent tx has not yet been relayed to us, but will be relayed in the near future.'));
|
' that the parent tx has not yet been relayed to us, but will be relayed in the near future.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
var output = tx.outputs[outputIndex];
|
var output = tx.outputs[outputIndex];
|
||||||
|
|
||||||
assert(output, 'Expected an output, but did not get one for tx: ' + tx.txid() + ' outputIndex: ' + outputIndex);
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (output == false) {
|
||||||
|
log.error('Expected an output, but did not get one for tx: ' + tx.txid() + ' outputIndex: ' + outputIndex);
|
||||||
|
}
|
||||||
|
// assert(output, 'Expected an output, but did not get one for tx: ' + tx.txid() + ' outputIndex: ' + outputIndex);
|
||||||
|
|
||||||
next(null, output.value);
|
next(null, output.value);
|
||||||
}
|
}
|
||||||
@ -375,7 +383,11 @@ TransactionService.prototype.onBlock = function(block, callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(block.txs.length === operations.length, 'It seems we are not indexing the correct number of transactions.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (block.txs.length != operations.length) {
|
||||||
|
log.error('It seems we are not indexing the correct number of transactions.');
|
||||||
|
}
|
||||||
|
// assert(block.txs.length === operations.length, 'It seems we are not indexing the correct number of transactions.');
|
||||||
|
|
||||||
callback(null, _.flattenDeep(operations));
|
callback(null, _.flattenDeep(operations));
|
||||||
});
|
});
|
||||||
@ -477,19 +489,30 @@ TransactionService.prototype._processTransaction = function(tx, opts, callback)
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(inputValues && inputValues.length === tx.inputs.length,
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
'Input values missing from tx.');
|
if (inputValues == false || inputValues.length != tx.inputs.length) {
|
||||||
|
log.error('Input values missing from tx.');
|
||||||
|
}
|
||||||
|
// assert(inputValues && inputValues.length === tx.inputs.length, 'Input values missing from tx.');
|
||||||
|
|
||||||
// inputValues
|
// inputValues
|
||||||
tx.__inputValues = inputValues;
|
tx.__inputValues = inputValues;
|
||||||
|
|
||||||
// timestamp
|
// timestamp
|
||||||
tx.__timestamp = self._getBlockTimestamp(opts.block.rhash());
|
tx.__timestamp = self._getBlockTimestamp(opts.block.rhash());
|
||||||
assert(tx.__timestamp, 'Timestamp is required when saving a transaction.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (tx.__timestamp == false) {
|
||||||
|
log.error('Timestamp is required when saving a transaction.');
|
||||||
|
}
|
||||||
|
// assert(tx.__timestamp, 'Timestamp is required when saving a transaction.');
|
||||||
|
|
||||||
// height
|
// height
|
||||||
tx.__height = opts.block.__height;
|
tx.__height = opts.block.__height;
|
||||||
assert(tx.__height, 'Block height is required when saving a trasnaction.');
|
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
|
||||||
|
if (tx.__height == false) {
|
||||||
|
log.error('Block height is required when saving a trasnaction.');
|
||||||
|
}
|
||||||
|
//assert(tx.__height, 'Block height is required when saving a trasnaction.');
|
||||||
|
|
||||||
// block hash
|
// block hash
|
||||||
tx.__blockhash = opts.block.rhash();
|
tx.__blockhash = opts.block.rhash();
|
||||||
|
|||||||
@ -4,6 +4,7 @@ var fs = require('fs');
|
|||||||
var http = require('http');
|
var http = require('http');
|
||||||
var https = require('https');
|
var https = require('https');
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
|
var express_ws = require('express-ws');
|
||||||
var bodyParser = require('body-parser');
|
var bodyParser = require('body-parser');
|
||||||
var socketio = require('socket.io');
|
var socketio = require('socket.io');
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
@ -105,7 +106,7 @@ WebService.prototype.setupAllRoutes = function() {
|
|||||||
|
|
||||||
if(service.getRoutePrefix && service.setupRoutes) {
|
if(service.getRoutePrefix && service.setupRoutes) {
|
||||||
this.app.use('/' + this.node.services[key].getRoutePrefix(), subApp);
|
this.app.use('/' + this.node.services[key].getRoutePrefix(), subApp);
|
||||||
this.node.services[key].setupRoutes(subApp, express);
|
this.node.services[key].setupRoutes(subApp, express, express_ws);
|
||||||
} else {
|
} else {
|
||||||
log.debug('No routes defined for: ' + key);
|
log.debug('No routes defined for: ' + key);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,12 +58,12 @@ utils.sendError = function(err, res) {
|
|||||||
|
|
||||||
utils.encodeTip = function(tip, name) {
|
utils.encodeTip = function(tip, name) {
|
||||||
var key = Buffer.concat([ constants.DB_PREFIX,
|
var key = Buffer.concat([ constants.DB_PREFIX,
|
||||||
Buffer.from('tip-' + name, 'utf8') ]);
|
new Buffer('tip-' + name, 'utf8') ]);
|
||||||
|
|
||||||
var heightBuf = Buffer.alloc(4);
|
var heightBuf = new Buffer(4);
|
||||||
heightBuf.writeUInt32BE(tip.height);
|
heightBuf.writeUInt32BE(tip.height);
|
||||||
|
|
||||||
var value = Buffer.concat([ heightBuf, Buffer.from(tip.hash, 'hex') ]);
|
var value = Buffer.concat([ heightBuf, new Buffer(tip.hash, 'hex') ]);
|
||||||
return { key: key, value: value };
|
return { key: key, value: value };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
13
package.json
13
package.json
@ -5,12 +5,12 @@
|
|||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"author": "BitPay <dev@bitpay.com>",
|
"author": "BitPay <dev@bitpay.com>",
|
||||||
"version": "5.0.8",
|
"version": "5.0.9-beta-rm",
|
||||||
"main": "./index.js",
|
"main": "./index.js",
|
||||||
"repository": "git://github.com/oipwg/flocore-node.git",
|
"repository": "git://github.com/ranchimall/flocore-node.git",
|
||||||
"homepage": "https://github.com/oipwg/flocore-node",
|
"homepage": "https://github.com/ranchimall/flocore-node",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/oipwg/flocore-node/issues"
|
"url": "https://github.com/ranchimall/flocore-node/issues"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"flocore-node": "./bin/flocore-node"
|
"flocore-node": "./bin/flocore-node"
|
||||||
@ -36,13 +36,14 @@
|
|||||||
"commander": "^2.8.1",
|
"commander": "^2.8.1",
|
||||||
"errno": "^0.1.4",
|
"errno": "^0.1.4",
|
||||||
"express": "^4.13.3",
|
"express": "^4.13.3",
|
||||||
|
"express-ws": "^5.0.2",
|
||||||
"fcoin": "^1.1.4",
|
"fcoin": "^1.1.4",
|
||||||
"flocore-lib": "^0.15.2",
|
"flocore-lib": "^0.15.2",
|
||||||
"flocore-message": "^1.0.7",
|
"flocore-message": "^1.0.7",
|
||||||
"flocore-p2p": "^5.0.0-beta.8",
|
"flocore-p2p": "^5.0.0-beta.8",
|
||||||
"florincoind-rpc": "0.7.1",
|
"florincoind-rpc": "0.7.1",
|
||||||
"flosight-api": "^5.0.0-beta.75",
|
"flosight-api": "github:ranchimall/flosight-api",
|
||||||
"flosight-ui": "^5.0.0-beta.72",
|
"flosight-ui": "github:ranchimall/flosight-ui",
|
||||||
"leveldown": "^2.0.0",
|
"leveldown": "^2.0.0",
|
||||||
"levelup": "^2.0.0",
|
"levelup": "^2.0.0",
|
||||||
"liftoff": "^2.2.0",
|
"liftoff": "^2.2.0",
|
||||||
|
|||||||
@ -6,27 +6,27 @@ var Encoding = require('../../../lib/services/address/encoding');
|
|||||||
|
|
||||||
describe('Address service encoding', function() {
|
describe('Address service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var txid = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
var txid = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
||||||
var address = '1EZBqbJSHFKSkVPNKzc5v26HA6nAHiTXq6';
|
var address = '1EZBqbJSHFKSkVPNKzc5v26HA6nAHiTXq6';
|
||||||
var height = 1;
|
var height = 1;
|
||||||
var addressSizeBuf = Buffer.alloc(1);
|
var addressSizeBuf = new Buffer(1);
|
||||||
var prefix0 = Buffer.from('00', 'hex');
|
var prefix0 = new Buffer('00', 'hex');
|
||||||
var prefix1 = Buffer.from('01', 'hex');
|
var prefix1 = new Buffer('01', 'hex');
|
||||||
var ts = Math.floor(new Date('2017-02-28').getTime() / 1000);
|
var ts = Math.floor(new Date('2017-02-28').getTime() / 1000);
|
||||||
var tsBuf = Buffer.alloc(4);
|
var tsBuf = new Buffer(4);
|
||||||
tsBuf.writeUInt32BE(ts);
|
tsBuf.writeUInt32BE(ts);
|
||||||
addressSizeBuf.writeUInt8(address.length);
|
addressSizeBuf.writeUInt8(address.length);
|
||||||
var addressIndexKeyBuf = Buffer.concat([
|
var addressIndexKeyBuf = Buffer.concat([
|
||||||
servicePrefix,
|
servicePrefix,
|
||||||
prefix0,
|
prefix0,
|
||||||
addressSizeBuf,
|
addressSizeBuf,
|
||||||
Buffer.from(address),
|
new Buffer(address),
|
||||||
Buffer.from('00000001', 'hex'),
|
new Buffer('00000001', 'hex'),
|
||||||
Buffer.from(txid, 'hex'),
|
new Buffer(txid, 'hex'),
|
||||||
Buffer.from('00000000', 'hex'),
|
new Buffer('00000000', 'hex'),
|
||||||
Buffer.from('00', 'hex'),
|
new Buffer('00', 'hex'),
|
||||||
tsBuf
|
tsBuf
|
||||||
]);
|
]);
|
||||||
var outputIndex = 5;
|
var outputIndex = 5;
|
||||||
@ -34,15 +34,15 @@ describe('Address service encoding', function() {
|
|||||||
servicePrefix,
|
servicePrefix,
|
||||||
prefix1,
|
prefix1,
|
||||||
addressSizeBuf,
|
addressSizeBuf,
|
||||||
Buffer.from(address),
|
new Buffer(address),
|
||||||
Buffer.from(txid, 'hex'),
|
new Buffer(txid, 'hex'),
|
||||||
Buffer.from('00000005', 'hex')]);
|
new Buffer('00000005', 'hex')]);
|
||||||
var txHex = '0100000001cc3ffe0638792c8b39328bb490caaefe2cf418f2ce0144956e0c22515f29724d010000006a473044022030ce9fa68d1a32abf0cd4adecf90fb998375b64fe887c6987278452b068ae74c022036a7d00d1c8af19e298e04f14294c807ebda51a20389ad751b4ff3c032cf8990012103acfcb348abb526526a9f63214639d79183871311c05b2eebc727adfdd016514fffffffff02f6ae7d04000000001976a9144455183e407ee4d3423858c8a3275918aedcd18e88aca99b9b08010000001976a9140beceae2c29bfde08d2b6d80b33067451c5887be88ac00000000';
|
var txHex = '0100000001cc3ffe0638792c8b39328bb490caaefe2cf418f2ce0144956e0c22515f29724d010000006a473044022030ce9fa68d1a32abf0cd4adecf90fb998375b64fe887c6987278452b068ae74c022036a7d00d1c8af19e298e04f14294c807ebda51a20389ad751b4ff3c032cf8990012103acfcb348abb526526a9f63214639d79183871311c05b2eebc727adfdd016514fffffffff02f6ae7d04000000001976a9144455183e407ee4d3423858c8a3275918aedcd18e88aca99b9b08010000001976a9140beceae2c29bfde08d2b6d80b33067451c5887be88ac00000000';
|
||||||
var tx = new flocore.Transaction(txHex);
|
var tx = new flocore.Transaction(txHex);
|
||||||
var sats = tx.outputs[0].satoshis;
|
var sats = tx.outputs[0].satoshis;
|
||||||
var satsBuf = Buffer.alloc(8);
|
var satsBuf = new Buffer(8);
|
||||||
satsBuf.writeDoubleBE(sats);
|
satsBuf.writeDoubleBE(sats);
|
||||||
var utxoValueBuf = Buffer.concat([Buffer.from('00000001', 'hex'), satsBuf, tsBuf, tx.outputs[0]._scriptBuffer]);
|
var utxoValueBuf = Buffer.concat([new Buffer('00000001', 'hex'), satsBuf, tsBuf, tx.outputs[0]._scriptBuffer]);
|
||||||
|
|
||||||
it('should encode address key' , function() {
|
it('should encode address key' , function() {
|
||||||
encoding.encodeAddressIndexKey(address, height, txid, 0, 0, ts).should.deep.equal(addressIndexKeyBuf);
|
encoding.encodeAddressIndexKey(address, height, txid, 0, 0, ts).should.deep.equal(addressIndexKeyBuf);
|
||||||
|
|||||||
@ -24,7 +24,7 @@ describe('Address Service', function() {
|
|||||||
services: []
|
services: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
addressService._encoding = new Encoding(Buffer.from('0000', 'hex'));
|
addressService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@ -34,7 +34,7 @@ describe('Address Service', function() {
|
|||||||
describe('#start', function() {
|
describe('#start', function() {
|
||||||
|
|
||||||
it('should get prefix for database', function(done) {
|
it('should get prefix for database', function(done) {
|
||||||
var getPrefix = sandbox.stub().callsArgWith(1, null, Buffer.from('ffee', 'hex'));
|
var getPrefix = sandbox.stub().callsArgWith(1, null, new Buffer('ffee', 'hex'));
|
||||||
addressService._db = { getPrefix: getPrefix };
|
addressService._db = { getPrefix: getPrefix };
|
||||||
addressService.start(function() {
|
addressService.start(function() {
|
||||||
expect(getPrefix.calledOnce).to.be.true;
|
expect(getPrefix.calledOnce).to.be.true;
|
||||||
@ -355,7 +355,7 @@ describe('Address Service', function() {
|
|||||||
describe('#getAddressUnspentOutputs', function() {
|
describe('#getAddressUnspentOutputs', function() {
|
||||||
it('should get address utxos', function(done) {
|
it('should get address utxos', function(done) {
|
||||||
|
|
||||||
var encoding = new Encoding(Buffer.from('0001', 'hex'));
|
var encoding = new Encoding(new Buffer('0001', 'hex'));
|
||||||
addressService._encoding = encoding;
|
addressService._encoding = encoding;
|
||||||
|
|
||||||
var address = 'a';
|
var address = 'a';
|
||||||
|
|||||||
@ -7,7 +7,7 @@ var Encoding = require('../../../lib/services/block/encoding');
|
|||||||
|
|
||||||
describe('Block service encoding', function() {
|
describe('Block service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
|
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var hash = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
var hash = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
||||||
@ -19,14 +19,14 @@ describe('Block service encoding', function() {
|
|||||||
it('should encode block key' , function() {
|
it('should encode block key' , function() {
|
||||||
encoding.encodeBlockKey(hash).should.deep.equal(Buffer.concat([
|
encoding.encodeBlockKey(hash).should.deep.equal(Buffer.concat([
|
||||||
servicePrefix,
|
servicePrefix,
|
||||||
Buffer.from(hash, 'hex')
|
new Buffer(hash, 'hex')
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode block key' , function() {
|
it('should decode block key' , function() {
|
||||||
var buf = Buffer.concat([
|
var buf = Buffer.concat([
|
||||||
servicePrefix,
|
servicePrefix,
|
||||||
Buffer.from(hash, 'hex')
|
new Buffer(hash, 'hex')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var actual = encoding.decodeBlockKey(buf);
|
var actual = encoding.decodeBlockKey(buf);
|
||||||
|
|||||||
@ -23,7 +23,7 @@ describe('Block Service', function() {
|
|||||||
services: []
|
services: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
blockService._encoding = new Encoding(Buffer.from('0000', 'hex'));
|
blockService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
|||||||
@ -121,7 +121,7 @@ describe('DB', function() {
|
|||||||
it('should put a value in the db', function(done) {
|
it('should put a value in the db', function(done) {
|
||||||
var put = sandbox.stub().callsArgWith(2, null);
|
var put = sandbox.stub().callsArgWith(2, null);
|
||||||
dbService._store = { put: put };
|
dbService._store = { put: put };
|
||||||
dbService.put(Buffer.from('key'), Buffer.from('value'), function(err) {
|
dbService.put(new Buffer('key'), new Buffer('value'), function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
return done(err);
|
return done(err);
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ describe('DB', function() {
|
|||||||
|
|
||||||
it('should not allow an operation while the node is shutting down', function(done) {
|
it('should not allow an operation while the node is shutting down', function(done) {
|
||||||
dbService._stopping = true;
|
dbService._stopping = true;
|
||||||
dbService.put(Buffer.from('key'), Buffer.from('value'), function(err) {
|
dbService.put(new Buffer('key'), new Buffer('value'), function(err) {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -256,7 +256,7 @@ describe('DB', function() {
|
|||||||
describe('#getServiceTip', function() {
|
describe('#getServiceTip', function() {
|
||||||
it('should get service tip for previously saved', function(done) {
|
it('should get service tip for previously saved', function(done) {
|
||||||
|
|
||||||
var tipBuf = Buffer.concat([ Buffer.from('deadbeef', 'hex'), Buffer.from(tx.txid(), 'hex') ]);
|
var tipBuf = Buffer.concat([ new Buffer('deadbeef', 'hex'), new Buffer(tx.txid(), 'hex') ]);
|
||||||
var get = sandbox.stub(dbService, 'get').callsArgWith(1, null, tipBuf);
|
var get = sandbox.stub(dbService, 'get').callsArgWith(1, null, tipBuf);
|
||||||
dbService.getServiceTip('test', function(err, tip) {
|
dbService.getServiceTip('test', function(err, tip) {
|
||||||
|
|
||||||
@ -293,7 +293,7 @@ describe('DB', function() {
|
|||||||
describe('#getPrefix', function() {
|
describe('#getPrefix', function() {
|
||||||
|
|
||||||
it('should get the db prefix for a service when one already exists', function(done) {
|
it('should get the db prefix for a service when one already exists', function(done) {
|
||||||
var get = sandbox.stub(dbService, 'get').callsArgWith(1, null, Buffer.from('0000', 'hex'));
|
var get = sandbox.stub(dbService, 'get').callsArgWith(1, null, new Buffer('0000', 'hex'));
|
||||||
dbService.getPrefix('test', function(err, prefix) {
|
dbService.getPrefix('test', function(err, prefix) {
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
@ -310,7 +310,7 @@ describe('DB', function() {
|
|||||||
var put = sandbox.stub(dbService, 'put').callsArgWith(2, null);
|
var put = sandbox.stub(dbService, 'put').callsArgWith(2, null);
|
||||||
var get = sandbox.stub(dbService, 'get');
|
var get = sandbox.stub(dbService, 'get');
|
||||||
get.onCall(0).callsArgWith(1, null, null);
|
get.onCall(0).callsArgWith(1, null, null);
|
||||||
get.onCall(1).callsArgWith(1, null, Buffer.from('eeee', 'hex'));
|
get.onCall(1).callsArgWith(1, null, new Buffer('eeee', 'hex'));
|
||||||
dbService.getPrefix('test', function(err, prefix) {
|
dbService.getPrefix('test', function(err, prefix) {
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
|
|||||||
@ -6,13 +6,13 @@ var Encoding = require('../../../lib/services/header/encoding');
|
|||||||
|
|
||||||
describe('Header service encoding', function() {
|
describe('Header service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
|
|
||||||
var hashPrefix = Buffer.from('00', 'hex');
|
var hashPrefix = new Buffer('00', 'hex');
|
||||||
var heightPrefix = Buffer.from('01', 'hex');
|
var heightPrefix = new Buffer('01', 'hex');
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var hash = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
var hash = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
||||||
var hashBuf = Buffer.from(hash, 'hex');
|
var hashBuf = new Buffer(hash, 'hex');
|
||||||
var header = {
|
var header = {
|
||||||
hash: hash,
|
hash: hash,
|
||||||
prevHash: '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03ade',
|
prevHash: '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03ade',
|
||||||
@ -25,15 +25,15 @@ describe('Header service encoding', function() {
|
|||||||
chainwork: '0000000000000000000000000000000000000000000000000000000200020002',
|
chainwork: '0000000000000000000000000000000000000000000000000000000200020002',
|
||||||
nextHash: '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03ade'
|
nextHash: '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03ade'
|
||||||
};
|
};
|
||||||
var versionBuf = Buffer.alloc(4);
|
var versionBuf = new Buffer(4);
|
||||||
var prevHashBuf = Buffer.from(header.prevHash, 'hex');
|
var prevHashBuf = new Buffer(header.prevHash, 'hex');
|
||||||
var nextHashBuf = Buffer.from(header.nextHash, 'hex');
|
var nextHashBuf = new Buffer(header.nextHash, 'hex');
|
||||||
var merkleRootBuf = Buffer.from(header.merkleRoot, 'hex');
|
var merkleRootBuf = new Buffer(header.merkleRoot, 'hex');
|
||||||
var tsBuf = Buffer.alloc(4);
|
var tsBuf = new Buffer(4);
|
||||||
var bitsBuf = Buffer.alloc(4);
|
var bitsBuf = new Buffer(4);
|
||||||
var nonceBuf = Buffer.alloc(4);
|
var nonceBuf = new Buffer(4);
|
||||||
var heightBuf = Buffer.alloc(4);
|
var heightBuf = new Buffer(4);
|
||||||
var chainBuf = Buffer.from('0000000000000000000000000000000000000000000000000000000200020002', 'hex');
|
var chainBuf = new Buffer('0000000000000000000000000000000000000000000000000000000200020002', 'hex');
|
||||||
heightBuf.writeUInt32BE(header.height);
|
heightBuf.writeUInt32BE(header.height);
|
||||||
|
|
||||||
it('should encode header hash key' , function() {
|
it('should encode header hash key' , function() {
|
||||||
@ -54,7 +54,7 @@ describe('Header service encoding', function() {
|
|||||||
.should.deep.equal(header.height);
|
.should.deep.equal(header.height);
|
||||||
});
|
});
|
||||||
it('should encode header value', function() {
|
it('should encode header value', function() {
|
||||||
var prevHashBuf = Buffer.from(header.prevHash, 'hex');
|
var prevHashBuf = new Buffer(header.prevHash, 'hex');
|
||||||
versionBuf.writeInt32BE(header.version); // signed
|
versionBuf.writeInt32BE(header.version); // signed
|
||||||
tsBuf.writeUInt32BE(header.timestamp);
|
tsBuf.writeUInt32BE(header.timestamp);
|
||||||
bitsBuf.writeUInt32BE(header.bits);
|
bitsBuf.writeUInt32BE(header.bits);
|
||||||
|
|||||||
@ -16,8 +16,8 @@ describe('Header Service', function() {
|
|||||||
|
|
||||||
var headerService;
|
var headerService;
|
||||||
var sandbox;
|
var sandbox;
|
||||||
var prevHeader = new Block(Buffer.from('01000000b25c0849b469983b4a5b90a49e4c0e4ba3853122ed141b5bd92d14000000000021a8aaa4995e4ce3b885677730b153741feda66a08492287a45c6a131671ba5a72ff504c5a0c011c456e4d060201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08045a0c011c028208ffffffff0100f2052a010000004341041994d910507ec4b2135dd32a4723caf00f8567f356ffbd5e703786d856b49a89d6597c280d8981238fbde81fa3767161bc3e994c17be41b42235a61c24c73459ac0000000001000000013b517d1aebd89b4034e0cf9b25ecbe82ef162ce71284e92a1f1adebf44ea1409000000008b483045022100c7ebc62e89740ddab42a64435c996e1c91a063f9f2cc004b4f023f7a1be5234402207608837faebec16049461d4ef7de807ce217040fd2a823a29da16ec07e463d440141048f108c0da4b5be3308e2e0b521d02d341de85b36a29285b47f00bc33e57a89cf4b6e76aa4a48ddc9a5e882620779e0f1b19dc98d478052fbd544167c745be1d8ffffffff010026e85a050000001976a914f760ef90462b0a4bde26d597c1f29324f5cd0fc488ac00000000', 'hex')).header.toObject();
|
var prevHeader = new Block(new Buffer('01000000b25c0849b469983b4a5b90a49e4c0e4ba3853122ed141b5bd92d14000000000021a8aaa4995e4ce3b885677730b153741feda66a08492287a45c6a131671ba5a72ff504c5a0c011c456e4d060201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08045a0c011c028208ffffffff0100f2052a010000004341041994d910507ec4b2135dd32a4723caf00f8567f356ffbd5e703786d856b49a89d6597c280d8981238fbde81fa3767161bc3e994c17be41b42235a61c24c73459ac0000000001000000013b517d1aebd89b4034e0cf9b25ecbe82ef162ce71284e92a1f1adebf44ea1409000000008b483045022100c7ebc62e89740ddab42a64435c996e1c91a063f9f2cc004b4f023f7a1be5234402207608837faebec16049461d4ef7de807ce217040fd2a823a29da16ec07e463d440141048f108c0da4b5be3308e2e0b521d02d341de85b36a29285b47f00bc33e57a89cf4b6e76aa4a48ddc9a5e882620779e0f1b19dc98d478052fbd544167c745be1d8ffffffff010026e85a050000001976a914f760ef90462b0a4bde26d597c1f29324f5cd0fc488ac00000000', 'hex')).header.toObject();
|
||||||
var preObjectHeader = new Block(Buffer.from('010000006a39821735ec18a366d95b391a7ff10dee181a198f1789b0550e0d00000000002b0c80fa52b669022c344c3e09e6bb9698ab90707bb4bb412af3fbf31cfd2163a601514c5a0c011c572aef0f0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08045a0c011c022003ffffffff0100f2052a01000000434104c5b694d72e601091fd733c6b18b94795c13e2db6b1474747e7be914b407854cad37cee3058f85373b9f9dbb0014e541c45851d5f85e83a1fd7c45e54423718f3ac00000000', 'hex')).header;
|
var preObjectHeader = new Block(new Buffer('010000006a39821735ec18a366d95b391a7ff10dee181a198f1789b0550e0d00000000002b0c80fa52b669022c344c3e09e6bb9698ab90707bb4bb412af3fbf31cfd2163a601514c5a0c011c572aef0f0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff08045a0c011c022003ffffffff0100f2052a01000000434104c5b694d72e601091fd733c6b18b94795c13e2db6b1474747e7be914b407854cad37cee3058f85373b9f9dbb0014e541c45851d5f85e83a1fd7c45e54423718f3ac00000000', 'hex')).header;
|
||||||
var header = preObjectHeader.toObject();
|
var header = preObjectHeader.toObject();
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
@ -26,7 +26,7 @@ describe('Header Service', function() {
|
|||||||
services: []
|
services: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
headerService._encoding = new Encoding(Buffer.from('0000', 'hex'));
|
headerService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@ -40,7 +40,7 @@ describe('Header Service', function() {
|
|||||||
|
|
||||||
var getServiceTip = sandbox.stub().callsArgWith(1, null, { height: 123, hash: 'a' });
|
var getServiceTip = sandbox.stub().callsArgWith(1, null, { height: 123, hash: 'a' });
|
||||||
var setListeners = sandbox.stub(headerService, '_setListeners');
|
var setListeners = sandbox.stub(headerService, '_setListeners');
|
||||||
var getPrefix = sandbox.stub().callsArgWith(1, null, Buffer.from('ffee', 'hex'));
|
var getPrefix = sandbox.stub().callsArgWith(1, null, new Buffer('ffee', 'hex'));
|
||||||
var adjustHeadersForCheckPointTip = sandbox.stub(headerService, '_adjustHeadersForCheckPointTip').callsArgWith(0, null);
|
var adjustHeadersForCheckPointTip = sandbox.stub(headerService, '_adjustHeadersForCheckPointTip').callsArgWith(0, null);
|
||||||
var setGenesisBlock = sandbox.stub(headerService, '_setGenesisBlock').callsArgWith(0, null);
|
var setGenesisBlock = sandbox.stub(headerService, '_setGenesisBlock').callsArgWith(0, null);
|
||||||
headerService.GENESIS_HASH = '00';
|
headerService.GENESIS_HASH = '00';
|
||||||
@ -159,8 +159,8 @@ describe('Header Service', function() {
|
|||||||
describe('#_computeChainwork', function() {
|
describe('#_computeChainwork', function() {
|
||||||
|
|
||||||
it('should calculate chain work correctly', function() {
|
it('should calculate chain work correctly', function() {
|
||||||
var expected = new BN(Buffer.from('000000000000000000000000000000000000000000677c7b8122f9902c79f4e0', 'hex'));
|
var expected = new BN(new Buffer('000000000000000000000000000000000000000000677c7b8122f9902c79f4e0', 'hex'));
|
||||||
var prev = new BN(Buffer.from('000000000000000000000000000000000000000000677bd68118a98f8779ea90', 'hex'));
|
var prev = new BN(new Buffer('000000000000000000000000000000000000000000677bd68118a98f8779ea90', 'hex'));
|
||||||
|
|
||||||
var actual = headerService._computeChainwork(0x18018d30, prev);
|
var actual = headerService._computeChainwork(0x18018d30, prev);
|
||||||
assert(actual.eq(expected), 'not equal: actual: ' + actual + ' expected: ' + expected);
|
assert(actual.eq(expected), 'not equal: actual: ' + actual + ' expected: ' + expected);
|
||||||
|
|||||||
@ -7,36 +7,36 @@ var Encoding = require('../../../lib/services/mempool/encoding');
|
|||||||
|
|
||||||
describe('Block service encoding', function() {
|
describe('Block service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
var txPrefix = Buffer.from('00', 'hex');
|
var txPrefix = new Buffer('00', 'hex');
|
||||||
var addressPrefix = Buffer.from('01', 'hex');
|
var addressPrefix = new Buffer('01', 'hex');
|
||||||
|
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var hash = '25e28f9fb0ada5353b7d98d85af5524b2f8df5b0b0e2d188f05968bceca603eb';
|
var hash = '25e28f9fb0ada5353b7d98d85af5524b2f8df5b0b0e2d188f05968bceca603eb';
|
||||||
var txString = '0100000004de9b4bb17f627096a9ee0b4528e4eae17df5b5c69edc29704c2e84a7371db29f010000006b483045022100f5b1a0d33b7be291c3953c25f8ae39d98601aa7099a8674daf638a08b86c7173022006ce372da5ad088a1cc6e5c49c2760a1b6f085eb1b51b502211b6bc9508661f9012102ec5e3731e54475dd2902326f43602a03ae3d62753324139163f81f20e787514cffffffff7a1d4e5fc2b8177ec738cd723a16cf2bf493791e55573445fc0df630fe5e2d64010000006b483045022100cf97f6cb8f126703e9768545dfb20ffb10ba78ae3d101aa46775f5a239b075fc02203150c4a89a11eaf5e404f4f96b62efa4455e9525765a025525c7105a7e47b6db012102c01e11b1d331f999bbdb83e8831de503cd52a01e3834a95ccafd615c67703d77ffffffff9e52447116415ca0d0567418a1a4ef8f27be3ff5a96bf87c922f3723d7db5d7c000000006b483045022100f6c117e536701be41a6b0b544d7c3b1091301e4e64a6265b6eb167b15d16959d022076916de4b115e700964194ce36a24cb9105f86482f4abbc63110c3f537cd5770012102ddf84cc7bee2d6a82ac09628a8ad4a26cd449fc528b81e7e6cc615707b8169dfffffffff5815d9750eb3572e30d6fd9df7afb4dbd76e042f3aa4988ac763b3fdf8397f80010000006a473044022028f4402b736066d93d2a32b28ccd3b7a21d84bb58fcd07fe392a611db94cdec5022018902ee0bf2c3c840c1b81ead4e6c87c88c48b2005bf5eea796464e561a620a8012102b6cdd1a6cd129ef796faeedb0b840fcd0ca00c57e16e38e46ee7028d59812ae7ffffffff0220a10700000000001976a914c342bcd1a7784d9842f7386b8b3b8a3d4171a06e88ac59611100000000001976a91449f8c749a9960dc29b5cbe7d2397cea7d26611bb88ac00000000';
|
var txString = '0100000004de9b4bb17f627096a9ee0b4528e4eae17df5b5c69edc29704c2e84a7371db29f010000006b483045022100f5b1a0d33b7be291c3953c25f8ae39d98601aa7099a8674daf638a08b86c7173022006ce372da5ad088a1cc6e5c49c2760a1b6f085eb1b51b502211b6bc9508661f9012102ec5e3731e54475dd2902326f43602a03ae3d62753324139163f81f20e787514cffffffff7a1d4e5fc2b8177ec738cd723a16cf2bf493791e55573445fc0df630fe5e2d64010000006b483045022100cf97f6cb8f126703e9768545dfb20ffb10ba78ae3d101aa46775f5a239b075fc02203150c4a89a11eaf5e404f4f96b62efa4455e9525765a025525c7105a7e47b6db012102c01e11b1d331f999bbdb83e8831de503cd52a01e3834a95ccafd615c67703d77ffffffff9e52447116415ca0d0567418a1a4ef8f27be3ff5a96bf87c922f3723d7db5d7c000000006b483045022100f6c117e536701be41a6b0b544d7c3b1091301e4e64a6265b6eb167b15d16959d022076916de4b115e700964194ce36a24cb9105f86482f4abbc63110c3f537cd5770012102ddf84cc7bee2d6a82ac09628a8ad4a26cd449fc528b81e7e6cc615707b8169dfffffffff5815d9750eb3572e30d6fd9df7afb4dbd76e042f3aa4988ac763b3fdf8397f80010000006a473044022028f4402b736066d93d2a32b28ccd3b7a21d84bb58fcd07fe392a611db94cdec5022018902ee0bf2c3c840c1b81ead4e6c87c88c48b2005bf5eea796464e561a620a8012102b6cdd1a6cd129ef796faeedb0b840fcd0ca00c57e16e38e46ee7028d59812ae7ffffffff0220a10700000000001976a914c342bcd1a7784d9842f7386b8b3b8a3d4171a06e88ac59611100000000001976a91449f8c749a9960dc29b5cbe7d2397cea7d26611bb88ac00000000';
|
||||||
var address = '1234567';
|
var address = '1234567';
|
||||||
var now = Math.floor(Date.now() / 1000);
|
var now = Math.floor(Date.now() / 1000);
|
||||||
var nowBuf = Buffer.alloc(4);
|
var nowBuf = new Buffer(4);
|
||||||
nowBuf.writeUInt32BE(now);
|
nowBuf.writeUInt32BE(now);
|
||||||
|
|
||||||
describe('Mempool', function() {
|
describe('Mempool', function() {
|
||||||
|
|
||||||
it('should encode mempool transaction key', function() {
|
it('should encode mempool transaction key', function() {
|
||||||
encoding.encodeMempoolTransactionKey(hash).should.deep.equal(Buffer.concat([ servicePrefix, txPrefix, Buffer.from(hash, 'hex') ]));
|
encoding.encodeMempoolTransactionKey(hash).should.deep.equal(Buffer.concat([ servicePrefix, txPrefix, new Buffer(hash, 'hex') ]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode mempool transaction key', function() {
|
it('should decode mempool transaction key', function() {
|
||||||
encoding.decodeMempoolTransactionKey(Buffer.concat([ servicePrefix, txPrefix, Buffer.from(hash, 'hex') ])).should.deep.equal(hash);
|
encoding.decodeMempoolTransactionKey(Buffer.concat([ servicePrefix, txPrefix, new Buffer(hash, 'hex') ])).should.deep.equal(hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should encode mempool transaction value', function() {
|
it('should encode mempool transaction value', function() {
|
||||||
var mytx = tx.fromRaw(txString, 'hex');
|
var mytx = tx.fromRaw(txString, 'hex');
|
||||||
mytx.__inputValues = [1012955, 447698, 446664, 391348];
|
mytx.__inputValues = [1012955, 447698, 446664, 391348];
|
||||||
encoding.encodeMempoolTransactionValue(mytx).should.deep.equal(Buffer.from(txString, 'hex'));
|
encoding.encodeMempoolTransactionValue(mytx).should.deep.equal(new Buffer(txString, 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode mempool transaction value', function() {
|
it('should decode mempool transaction value', function() {
|
||||||
var mytx = encoding.decodeMempoolTransactionValue(Buffer.from(txString, 'hex'));
|
var mytx = encoding.decodeMempoolTransactionValue(new Buffer(txString, 'hex'));
|
||||||
mytx.should.deep.equal(tx.fromRaw(txString, 'hex'));
|
mytx.should.deep.equal(tx.fromRaw(txString, 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -46,11 +46,11 @@ describe('Block service encoding', function() {
|
|||||||
.should.deep.equal(Buffer.concat([
|
.should.deep.equal(Buffer.concat([
|
||||||
servicePrefix,
|
servicePrefix,
|
||||||
addressPrefix,
|
addressPrefix,
|
||||||
Buffer.from('07', 'hex'),
|
new Buffer('07', 'hex'),
|
||||||
Buffer.from(address),
|
new Buffer(address),
|
||||||
Buffer.from(hash, 'hex'),
|
new Buffer(hash, 'hex'),
|
||||||
Buffer.from('00000000', 'hex'),
|
new Buffer('00000000', 'hex'),
|
||||||
Buffer.from('01', 'hex')
|
new Buffer('01', 'hex')
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -58,11 +58,11 @@ describe('Block service encoding', function() {
|
|||||||
encoding.decodeMempoolAddressKey(Buffer.concat([
|
encoding.decodeMempoolAddressKey(Buffer.concat([
|
||||||
servicePrefix,
|
servicePrefix,
|
||||||
addressPrefix,
|
addressPrefix,
|
||||||
Buffer.from('07', 'hex'),
|
new Buffer('07', 'hex'),
|
||||||
Buffer.from(address),
|
new Buffer(address),
|
||||||
Buffer.from(hash, 'hex'),
|
new Buffer(hash, 'hex'),
|
||||||
Buffer.from('00000000', 'hex'),
|
new Buffer('00000000', 'hex'),
|
||||||
Buffer.from('01', 'hex') ])).should.deep.equal({
|
new Buffer('01', 'hex') ])).should.deep.equal({
|
||||||
address: address,
|
address: address,
|
||||||
txid: hash,
|
txid: hash,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|||||||
@ -21,7 +21,7 @@ describe('Mempool Service', function() {
|
|||||||
services: []
|
services: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mempoolService._encoding = new Encoding(Buffer.from('0000', 'hex'));
|
mempoolService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@ -31,7 +31,7 @@ describe('Mempool Service', function() {
|
|||||||
describe('#start', function() {
|
describe('#start', function() {
|
||||||
|
|
||||||
it('should get the db prefix', function(done) {
|
it('should get the db prefix', function(done) {
|
||||||
var getPrefix = sandbox.stub().callsArgWith(1, null, Buffer.from('0001', 'hex'));
|
var getPrefix = sandbox.stub().callsArgWith(1, null, new Buffer('0001', 'hex'));
|
||||||
mempoolService._db = { getPrefix: getPrefix };
|
mempoolService._db = { getPrefix: getPrefix };
|
||||||
|
|
||||||
mempoolService.start(function() {
|
mempoolService.start(function() {
|
||||||
|
|||||||
@ -5,21 +5,21 @@ var Encoding = require('../../../lib/services/timestamp/encoding');
|
|||||||
|
|
||||||
describe('Timestamp service encoding', function() {
|
describe('Timestamp service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
var blockPrefix = Buffer.from('00', 'hex');
|
var blockPrefix = new Buffer('00', 'hex');
|
||||||
var timestampPrefix = Buffer.from('01', 'hex');
|
var timestampPrefix = new Buffer('01', 'hex');
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var blockhash = '00000000000000000115b92b1ff4377441049bff75c6c48b626eb99e8b744297';
|
var blockhash = '00000000000000000115b92b1ff4377441049bff75c6c48b626eb99e8b744297';
|
||||||
var timestamp = 5;
|
var timestamp = 5;
|
||||||
var timestampBuf = Buffer.alloc(4);
|
var timestampBuf = new Buffer(4);
|
||||||
timestampBuf.writeUInt32BE(timestamp);
|
timestampBuf.writeUInt32BE(timestamp);
|
||||||
|
|
||||||
it('should encode block timestamp key' , function() {
|
it('should encode block timestamp key' , function() {
|
||||||
encoding.encodeBlockTimestampKey(blockhash).should.deep.equal(Buffer.concat([servicePrefix, blockPrefix, Buffer.from(blockhash, 'hex')]));
|
encoding.encodeBlockTimestampKey(blockhash).should.deep.equal(Buffer.concat([servicePrefix, blockPrefix, new Buffer(blockhash, 'hex')]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode block timestamp key', function() {
|
it('should decode block timestamp key', function() {
|
||||||
var blockTimestampKey = encoding.decodeBlockTimestampKey(Buffer.concat([servicePrefix, blockPrefix, Buffer.from(blockhash, 'hex')]));
|
var blockTimestampKey = encoding.decodeBlockTimestampKey(Buffer.concat([servicePrefix, blockPrefix, new Buffer(blockhash, 'hex')]));
|
||||||
blockTimestampKey.should.equal(blockhash);
|
blockTimestampKey.should.equal(blockhash);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -40,10 +40,10 @@ describe('Timestamp service encoding', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should encode timestamp block value', function() {
|
it('should encode timestamp block value', function() {
|
||||||
encoding.encodeTimestampBlockValue(blockhash).should.deep.equal(Buffer.from(blockhash, 'hex'));
|
encoding.encodeTimestampBlockValue(blockhash).should.deep.equal(new Buffer(blockhash, 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode timestamp block value', function() {
|
it('should decode timestamp block value', function() {
|
||||||
encoding.decodeTimestampBlockValue(Buffer.from(blockhash, 'hex')).should.equal(blockhash);
|
encoding.decodeTimestampBlockValue(new Buffer(blockhash, 'hex')).should.equal(blockhash);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,24 +6,24 @@ var Encoding = require('../../../lib/services/transaction/encoding');
|
|||||||
|
|
||||||
describe('Transaction service encoding', function() {
|
describe('Transaction service encoding', function() {
|
||||||
|
|
||||||
var servicePrefix = Buffer.from('0000', 'hex');
|
var servicePrefix = new Buffer('0000', 'hex');
|
||||||
|
|
||||||
var encoding = new Encoding(servicePrefix);
|
var encoding = new Encoding(servicePrefix);
|
||||||
var txid = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
var txid = '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03add';
|
||||||
var blockHash = txid;
|
var blockHash = txid;
|
||||||
var txHex = '0100000001cc3ffe0638792c8b39328bb490caaefe2cf418f2ce0144956e0c22515f29724d010000006a473044022030ce9fa68d1a32abf0cd4adecf90fb998375b64fe887c6987278452b068ae74c022036a7d00d1c8af19e298e04f14294c807ebda51a20389ad751b4ff3c032cf8990012103acfcb348abb526526a9f63214639d79183871311c05b2eebc727adfdd016514fffffffff02f6ae7d04000000001976a9144455183e407ee4d3423858c8a3275918aedcd18e88aca99b9b08010000001976a9140beceae2c29bfde08d2b6d80b33067451c5887be88ac00000000';
|
var txHex = '0100000001cc3ffe0638792c8b39328bb490caaefe2cf418f2ce0144956e0c22515f29724d010000006a473044022030ce9fa68d1a32abf0cd4adecf90fb998375b64fe887c6987278452b068ae74c022036a7d00d1c8af19e298e04f14294c807ebda51a20389ad751b4ff3c032cf8990012103acfcb348abb526526a9f63214639d79183871311c05b2eebc727adfdd016514fffffffff02f6ae7d04000000001976a9144455183e407ee4d3423858c8a3275918aedcd18e88aca99b9b08010000001976a9140beceae2c29bfde08d2b6d80b33067451c5887be88ac00000000';
|
||||||
var tx = Tx.fromRaw(txHex, 'hex');
|
var tx = Tx.fromRaw(txHex, 'hex');
|
||||||
var txEncoded = Buffer.concat([Buffer.from('00000002', 'hex'), Buffer.from(blockHash, 'hex'), Buffer.from('00000001', 'hex'), Buffer.from('0002', 'hex'), Buffer.from('40000000000000004008000000000000', 'hex'), tx.toRaw()]);
|
var txEncoded = Buffer.concat([new Buffer('00000002', 'hex'), new Buffer(blockHash, 'hex'), new Buffer('00000001', 'hex'), new Buffer('0002', 'hex'), new Buffer('40000000000000004008000000000000', 'hex'), tx.toRaw()]);
|
||||||
var indexBuf = Buffer.alloc(4);
|
var indexBuf = new Buffer(4);
|
||||||
indexBuf.writeUInt32BE(3);
|
indexBuf.writeUInt32BE(3);
|
||||||
|
|
||||||
it('should encode transaction key' , function() {
|
it('should encode transaction key' , function() {
|
||||||
var txBuf = Buffer.from(txid, 'hex');
|
var txBuf = new Buffer(txid, 'hex');
|
||||||
encoding.encodeTransactionKey(txid).should.deep.equal(Buffer.concat([servicePrefix, Buffer.from('00', 'hex'), txBuf]));
|
encoding.encodeTransactionKey(txid).should.deep.equal(Buffer.concat([servicePrefix, new Buffer('00', 'hex'), txBuf]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode transaction key', function() {
|
it('should decode transaction key', function() {
|
||||||
encoding.decodeTransactionKey(Buffer.concat([servicePrefix, Buffer.from('00', 'hex'), Buffer.from(txid, 'hex')]))
|
encoding.decodeTransactionKey(Buffer.concat([servicePrefix, new Buffer('00', 'hex'), new Buffer(txid, 'hex')]))
|
||||||
.should.equal(txid);
|
.should.equal(txid);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,21 +47,21 @@ describe('Transaction service encoding', function() {
|
|||||||
|
|
||||||
it('should encode spent key', function() {
|
it('should encode spent key', function() {
|
||||||
encoding.encodeSpentKey(txid, 3).should.deep.equal(Buffer.concat([servicePrefix,
|
encoding.encodeSpentKey(txid, 3).should.deep.equal(Buffer.concat([servicePrefix,
|
||||||
Buffer.from('01', 'hex'), Buffer.from(txid, 'hex'), indexBuf]));
|
new Buffer('01', 'hex'), new Buffer(txid, 'hex'), indexBuf]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode spent key', function() {
|
it('should decode spent key', function() {
|
||||||
encoding.decodeSpentKey(Buffer.concat([servicePrefix,
|
encoding.decodeSpentKey(Buffer.concat([servicePrefix,
|
||||||
Buffer.from('01', 'hex'), Buffer.from(txid, 'hex'), indexBuf])).should.deep.equal({ txid: txid, outputIndex: 3 });
|
new Buffer('01', 'hex'), new Buffer(txid, 'hex'), indexBuf])).should.deep.equal({ txid: txid, outputIndex: 3 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should encode spent value', function() {
|
it('should encode spent value', function() {
|
||||||
encoding.encodeSpentValue(txid, 3, 3, txid).should.deep.equal(Buffer.concat([Buffer.from(txid, 'hex'), indexBuf, indexBuf, Buffer.from(blockHash, 'hex')]));
|
encoding.encodeSpentValue(txid, 3, 3, txid).should.deep.equal(Buffer.concat([new Buffer(txid, 'hex'), indexBuf, indexBuf, new Buffer(blockHash, 'hex')]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode spent value', function() {
|
it('should decode spent value', function() {
|
||||||
encoding.decodeSpentValue(Buffer.concat([Buffer.from(txid, 'hex'), indexBuf,
|
encoding.decodeSpentValue(Buffer.concat([new Buffer(txid, 'hex'), indexBuf,
|
||||||
indexBuf, Buffer.from(blockHash, 'hex')]))
|
indexBuf, new Buffer(blockHash, 'hex')]))
|
||||||
.should.deep.equal({ txid: txid, inputIndex: 3, blockHeight: 3, blockHash: blockHash });
|
.should.deep.equal({ txid: txid, inputIndex: 3, blockHeight: 3, blockHash: blockHash });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -21,7 +21,7 @@ describe('Transaction Service', function() {
|
|||||||
services: []
|
services: []
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
txService._encoding = new Encoding(Buffer.from('0000', 'hex'));
|
txService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
@ -30,7 +30,7 @@ describe('Transaction Service', function() {
|
|||||||
|
|
||||||
describe('#start', function() {
|
describe('#start', function() {
|
||||||
it('should get the prefix and the service tip', function(done) {
|
it('should get the prefix and the service tip', function(done) {
|
||||||
var getPrefix = sandbox.stub().callsArgWith(1, null, Buffer.from('ffee', 'hex'));
|
var getPrefix = sandbox.stub().callsArgWith(1, null, new Buffer('ffee', 'hex'));
|
||||||
txService._db = { getPrefix: getPrefix };
|
txService._db = { getPrefix: getPrefix };
|
||||||
txService.start(function() {
|
txService.start(function() {
|
||||||
getPrefix.calledOnce.should.be.true;
|
getPrefix.calledOnce.should.be.true;
|
||||||
|
|||||||
@ -39,13 +39,13 @@ describe('Utils', function() {
|
|||||||
|
|
||||||
describe('#getTerminalKey', function() {
|
describe('#getTerminalKey', function() {
|
||||||
it('should get the terminal key for a buffer', function() {
|
it('should get the terminal key for a buffer', function() {
|
||||||
utils.getTerminalKey(Buffer.from('ffff', 'hex'))
|
utils.getTerminalKey(new Buffer('ffff', 'hex'))
|
||||||
.should.deep.equal(Buffer.from('010000', 'hex'));
|
.should.deep.equal(new Buffer('010000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get the terminal key for a large buffer', function() {
|
it('should get the terminal key for a large buffer', function() {
|
||||||
utils.getTerminalKey(Buffer.concat([ Buffer.from(new Array(64).join('f'), 'hex'), Buffer.from('fe', 'hex') ]))
|
utils.getTerminalKey(Buffer.concat([ new Buffer(new Array(64).join('f'), 'hex'), new Buffer('fe', 'hex') ]))
|
||||||
.should.deep.equal(Buffer.from('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'hex'));
|
.should.deep.equal(new Buffer('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 'hex'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,8 +91,8 @@ describe('Utils', function() {
|
|||||||
it('should encode tip', function() {
|
it('should encode tip', function() {
|
||||||
var res = utils.encodeTip({ height: 0xdeadbeef, hash: new Array(65).join('0') }, 'test');
|
var res = utils.encodeTip({ height: 0xdeadbeef, hash: new Array(65).join('0') }, 'test');
|
||||||
res.should.deep.equal({
|
res.should.deep.equal({
|
||||||
key: Buffer.from('ffff7469702d74657374', 'hex'),
|
key: new Buffer('ffff7469702d74657374', 'hex'),
|
||||||
value: Buffer.from('deadbeef00000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
value: new Buffer('deadbeef00000000000000000000000000000000000000000000000000000000000000000', 'hex')
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user