146 lines
2.5 KiB
JavaScript
146 lines
2.5 KiB
JavaScript
/*!
|
|
* common.js - commonly required functions for wallet.
|
|
* Copyright (c) 2014-2017, Christopher Jeffrey (MIT License).
|
|
* https://github.com/bcoin-org/bcoin
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* @exports wallet/common
|
|
*/
|
|
|
|
const common = exports;
|
|
|
|
/**
|
|
* Test whether a string is eligible
|
|
* to be used as a name or ID.
|
|
* @param {String} key
|
|
* @returns {Boolean}
|
|
*/
|
|
|
|
common.isName = function isName(key) {
|
|
if (typeof key !== 'string')
|
|
return false;
|
|
|
|
if (key.length === 0)
|
|
return false;
|
|
|
|
if (!/^[\-\._0-9A-Za-z]+$/.test(key))
|
|
return false;
|
|
|
|
// Prevents __proto__
|
|
// from being used.
|
|
switch (key[0]) {
|
|
case '_':
|
|
case '-':
|
|
case '.':
|
|
return false;
|
|
}
|
|
|
|
switch (key[key.length - 1]) {
|
|
case '_':
|
|
case '-':
|
|
case '.':
|
|
return false;
|
|
}
|
|
|
|
return key.length >= 1 && key.length <= 40;
|
|
};
|
|
|
|
/**
|
|
* Sort an array of transactions by time.
|
|
* @param {TX[]} txs
|
|
* @returns {TX[]}
|
|
*/
|
|
|
|
common.sortTX = function sortTX(txs) {
|
|
return txs.sort((a, b) => {
|
|
return a.mtime - b.mtime;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Sort an array of coins by height.
|
|
* @param {Coin[]} txs
|
|
* @returns {Coin[]}
|
|
*/
|
|
|
|
common.sortCoins = function sortCoins(coins) {
|
|
return coins.sort((a, b) => {
|
|
a = a.height === -1 ? 0x7fffffff : a.height;
|
|
b = b.height === -1 ? 0x7fffffff : b.height;
|
|
return a - b;
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Sort an array of transactions in dependency order.
|
|
* @param {TX[]} txs
|
|
* @returns {TX[]}
|
|
*/
|
|
|
|
common.sortDeps = function sortDeps(txs) {
|
|
const map = new Map();
|
|
|
|
for (const tx of txs) {
|
|
const hash = tx.hash('hex');
|
|
map.set(hash, tx);
|
|
}
|
|
|
|
const depMap = new Map();
|
|
const depCount = new Map();
|
|
const top = [];
|
|
|
|
for (const [hash, tx] of map) {
|
|
depCount.set(hash, 0);
|
|
|
|
let hasDeps = false;
|
|
|
|
for (const input of tx.inputs) {
|
|
const prev = input.prevout.hash;
|
|
|
|
if (!map.has(prev))
|
|
continue;
|
|
|
|
const count = depCount.get(hash);
|
|
depCount.set(hash, count + 1);
|
|
hasDeps = true;
|
|
|
|
if (!depMap.has(prev))
|
|
depMap.set(prev, []);
|
|
|
|
depMap.get(prev).push(tx);
|
|
}
|
|
|
|
if (hasDeps)
|
|
continue;
|
|
|
|
top.push(tx);
|
|
}
|
|
|
|
const result = [];
|
|
|
|
for (const tx of top) {
|
|
const hash = tx.hash('hex');
|
|
const deps = depMap.get(hash);
|
|
|
|
result.push(tx);
|
|
|
|
if (!deps)
|
|
continue;
|
|
|
|
for (const tx of deps) {
|
|
const hash = tx.hash('hex');
|
|
let count = depCount.get(hash);
|
|
|
|
if (--count === 0)
|
|
top.push(tx);
|
|
|
|
depCount.set(hash, count);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|