scanning.
This commit is contained in:
parent
5095f78dbf
commit
a95ab18379
@ -126,8 +126,12 @@ Address.prototype.toScript = function toScript() {
|
|||||||
* @returns {Base58String}
|
* @returns {Base58String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toString = function toString() {
|
Address.prototype.toString = function toString(enc) {
|
||||||
return this.toBase58();
|
if (enc === 'hex')
|
||||||
|
return this.getHash('hex');
|
||||||
|
if (enc === 'base58')
|
||||||
|
enc = null;
|
||||||
|
return this.toBase58(enc);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -175,7 +175,7 @@ Mnemonic.prototype.toSeed = function toSeed() {
|
|||||||
if (!this.phrase)
|
if (!this.phrase)
|
||||||
this.phrase = this.createMnemonic();
|
this.phrase = this.createMnemonic();
|
||||||
|
|
||||||
this.seed = utils.pbkdf2(
|
this.seed = utils.pbkdf2Sync(
|
||||||
nfkd(this.phrase),
|
nfkd(this.phrase),
|
||||||
nfkd('mnemonic' + this.passphrase),
|
nfkd('mnemonic' + this.passphrase),
|
||||||
2048, 64, 'sha512');
|
2048, 64, 'sha512');
|
||||||
@ -1083,9 +1083,9 @@ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
|||||||
|
|
||||||
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
||||||
var p = new BufferReader(raw);
|
var p = new BufferReader(raw);
|
||||||
var i, type, prefix;
|
var i, version, type, prefix;
|
||||||
|
|
||||||
this.version = p.readU32BE();
|
version = p.readU32BE();
|
||||||
this.depth = p.readU8();
|
this.depth = p.readU8();
|
||||||
this.parentFingerPrint = p.readBytes(4);
|
this.parentFingerPrint = p.readBytes(4);
|
||||||
this.childIndex = p.readU32BE();
|
this.childIndex = p.readU32BE();
|
||||||
@ -1097,7 +1097,7 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
|
|||||||
for (i = 0; i < network.types.length; i++) {
|
for (i = 0; i < network.types.length; i++) {
|
||||||
type = network.types[i];
|
type = network.types[i];
|
||||||
prefix = network[type].prefixes.xprivkey;
|
prefix = network[type].prefixes.xprivkey;
|
||||||
if (this.version === prefix)
|
if (version === prefix)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,9 +1616,9 @@ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
|||||||
|
|
||||||
HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
||||||
var p = new BufferReader(raw);
|
var p = new BufferReader(raw);
|
||||||
var i, type, prefix;
|
var i, version, type, prefix;
|
||||||
|
|
||||||
this.version = p.readU32BE();
|
version = p.readU32BE();
|
||||||
this.depth = p.readU8();
|
this.depth = p.readU8();
|
||||||
this.parentFingerPrint = p.readBytes(4);
|
this.parentFingerPrint = p.readBytes(4);
|
||||||
this.childIndex = p.readU32BE();
|
this.childIndex = p.readU32BE();
|
||||||
@ -1629,7 +1629,7 @@ HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
|
|||||||
for (i = 0; i < network.types.length; i++) {
|
for (i = 0; i < network.types.length; i++) {
|
||||||
type = network.types[i];
|
type = network.types[i];
|
||||||
prefix = network[type].prefixes.xpubkey;
|
prefix = network[type].prefixes.xpubkey;
|
||||||
if (this.version === prefix)
|
if (version === prefix)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -776,7 +776,7 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
|||||||
options = {};
|
options = {};
|
||||||
|
|
||||||
if (options instanceof bcoin.wallet)
|
if (options instanceof bcoin.wallet)
|
||||||
options = { wallet: options, m: options.m, n: options.n };
|
options = { wallet: options };
|
||||||
|
|
||||||
if (options.wallet)
|
if (options.wallet)
|
||||||
wallet = options.wallet;
|
wallet = options.wallet;
|
||||||
@ -791,6 +791,7 @@ MTX.prototype.maxSize = function maxSize(options, force) {
|
|||||||
if (!wallet)
|
if (!wallet)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Hack
|
||||||
address = wallet.receiveAddress;
|
address = wallet.receiveAddress;
|
||||||
|
|
||||||
if (address.program && hash.length === 20)
|
if (address.program && hash.length === 20)
|
||||||
|
|||||||
@ -33,7 +33,6 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var crypto = require('crypto');
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,7 +69,7 @@ function scrypt(passwd, salt, N, r, p, len, callback) {
|
|||||||
XY = new Buffer(256 * r);
|
XY = new Buffer(256 * r);
|
||||||
V = new Buffer(128 * r * N);
|
V = new Buffer(128 * r * N);
|
||||||
|
|
||||||
crypto.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256', function(err, B) {
|
utils.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256', function(err, B) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -80,7 +79,7 @@ function scrypt(passwd, salt, N, r, p, len, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
crypto.pbkdf2(passwd, B, 1, len, 'sha256', callback);
|
utils.pbkdf2(passwd, B, 1, len, 'sha256', callback);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,12 +69,12 @@ function scrypt(passwd, salt, N, r, p, len) {
|
|||||||
XY = new Buffer(256 * r);
|
XY = new Buffer(256 * r);
|
||||||
V = new Buffer(128 * r * N);
|
V = new Buffer(128 * r * N);
|
||||||
|
|
||||||
B = utils.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256');
|
B = utils.pbkdf2Sync(passwd, salt, 1, p * 128 * r, 'sha256');
|
||||||
|
|
||||||
for (i = 0; i < p; i++)
|
for (i = 0; i < p; i++)
|
||||||
smix(B, i * 128 * r, r, N, V, XY);
|
smix(B, i * 128 * r, r, N, V, XY);
|
||||||
|
|
||||||
return utils.pbkdf2(passwd, B, 1, len, 'sha256');
|
return utils.pbkdf2Sync(passwd, B, 1, len, 'sha256');
|
||||||
}
|
}
|
||||||
|
|
||||||
function salsa20_8(B) {
|
function salsa20_8(B) {
|
||||||
|
|||||||
@ -201,15 +201,61 @@ WalletMap.prototype.getPaths = function getPaths(address) {
|
|||||||
return this.table[address];
|
return this.table[address];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
WalletMap.prototype.toJSON = function toJSON() {
|
||||||
|
return {
|
||||||
|
inputs: this.inputs.map(function(input) {
|
||||||
|
return input.toJSON();
|
||||||
|
}),
|
||||||
|
outputs: this.outputs.map(function(output) {
|
||||||
|
return output.toJSON();
|
||||||
|
}),
|
||||||
|
paths: this.paths.map(function(path) {
|
||||||
|
return path.toJSON();
|
||||||
|
}),
|
||||||
|
accounts: this.accounts.map(function(path) {
|
||||||
|
return {
|
||||||
|
id: path.id,
|
||||||
|
name: path.name,
|
||||||
|
account: path.account
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
wallets: this.wallets
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
function MapMember() {
|
function MapMember() {
|
||||||
this.value = 0;
|
this.value = 0;
|
||||||
this.hash = null;
|
this.address = null;
|
||||||
this.wallets = [];
|
|
||||||
this.paths = [];
|
this.paths = [];
|
||||||
|
this.accounts = [];
|
||||||
|
this.wallets = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapMember.prototype.toJSON = function toJSON() {
|
||||||
|
return {
|
||||||
|
value: utils.btc(this.value),
|
||||||
|
address: this.address
|
||||||
|
? this.address.toBase58()
|
||||||
|
: null,
|
||||||
|
hash: this.address
|
||||||
|
? this.address.getHash('hex')
|
||||||
|
: null,
|
||||||
|
paths: this.paths.map(function(path) {
|
||||||
|
return path.toJSON();
|
||||||
|
}),
|
||||||
|
accounts: this.accounts.map(function(path) {
|
||||||
|
return {
|
||||||
|
id: path.id,
|
||||||
|
name: path.name,
|
||||||
|
account: path.account
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
wallets: this.wallets
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
MapMember.fromMember = function fromMember(table, io) {
|
MapMember.fromMember = function fromMember(table, io) {
|
||||||
var hash = io.getHash('hex');
|
var address = io.getAddress();
|
||||||
var member = new MapMember();
|
var member = new MapMember();
|
||||||
var i, paths;
|
var i, paths;
|
||||||
|
|
||||||
@ -217,19 +263,20 @@ MapMember.fromMember = function fromMember(table, io) {
|
|||||||
? io.coin.value
|
? io.coin.value
|
||||||
: io.value || 0;
|
: io.value || 0;
|
||||||
|
|
||||||
if (!hash)
|
if (!address)
|
||||||
return member;
|
return member;
|
||||||
|
|
||||||
paths = table[hash];
|
paths = table[address.getHash('hex')];
|
||||||
|
|
||||||
assert(paths);
|
assert(paths);
|
||||||
|
|
||||||
member.hash = hash;
|
member.address = address;
|
||||||
member.paths = paths;
|
member.paths = paths;
|
||||||
|
|
||||||
for (i = 0; i < paths.length; i++)
|
for (i = 0; i < paths.length; i++)
|
||||||
member.wallets.push(paths[i].id);
|
member.wallets.push(paths[i].id);
|
||||||
|
|
||||||
|
member.accounts = uniq(member.paths);
|
||||||
member.wallets = utils.uniq(member.wallets);
|
member.wallets = utils.uniq(member.wallets);
|
||||||
|
|
||||||
return member;
|
return member;
|
||||||
@ -258,7 +305,7 @@ TXDB.prototype.getMap = function getMap(tx, callback) {
|
|||||||
|
|
||||||
map = WalletMap.fromTX(table, tx);
|
map = WalletMap.fromTX(table, tx);
|
||||||
|
|
||||||
utils.print(map);
|
utils.print(map.toJSON());
|
||||||
|
|
||||||
return callback(null, map);
|
return callback(null, map);
|
||||||
});
|
});
|
||||||
@ -276,7 +323,7 @@ TXDB.prototype.mapAddresses = function mapAddresses(address, callback) {
|
|||||||
var count = 0;
|
var count = 0;
|
||||||
var i, keys, values;
|
var i, keys, values;
|
||||||
|
|
||||||
return utils.forEachSerial(address, function(address, next) {
|
utils.forEachSerial(address, function(address, next) {
|
||||||
self.walletdb.getAddress(address, function(err, paths) {
|
self.walletdb.getAddress(address, function(err, paths) {
|
||||||
if (err)
|
if (err)
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|||||||
@ -358,7 +358,7 @@ utils.hmac = function hmac(alg, data, salt) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
utils.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
utils.pbkdf2Sync = function pbkdf2Sync(key, salt, iter, len, alg) {
|
||||||
if (typeof key === 'string')
|
if (typeof key === 'string')
|
||||||
key = new Buffer(key, 'utf8');
|
key = new Buffer(key, 'utf8');
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ utils.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) {
|
|||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
utils.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) {
|
utils.pbkdf2 = function pbkdf2(key, salt, iter, len, alg, callback) {
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
if (typeof key === 'string')
|
if (typeof key === 'string')
|
||||||
@ -403,13 +403,13 @@ utils.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Derive a key using pbkdf2 with 25,000 iterations.
|
* Derive a key using pbkdf2 with 50,000 iterations.
|
||||||
* @param {Buffer|String} passphrase
|
* @param {Buffer|String} passphrase
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
|
|
||||||
utils.derive = function derive(passphrase, callback) {
|
utils.derive = function derive(passphrase, callback) {
|
||||||
utils.pbkdf2Async(passphrase, 'bcoin', 25000, 32, 'sha256', callback);
|
utils.pbkdf2(passphrase, 'bcoin', 50000, 32, 'sha256', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -423,6 +423,7 @@ utils.derive = function derive(passphrase, callback) {
|
|||||||
utils.encrypt = function encrypt(data, passphrase, iv, callback) {
|
utils.encrypt = function encrypt(data, passphrase, iv, callback) {
|
||||||
assert(Buffer.isBuffer(data));
|
assert(Buffer.isBuffer(data));
|
||||||
assert(passphrase, 'No passphrase.');
|
assert(passphrase, 'No passphrase.');
|
||||||
|
assert(Buffer.isBuffer(iv));
|
||||||
|
|
||||||
utils.derive(passphrase, function(err, key) {
|
utils.derive(passphrase, function(err, key) {
|
||||||
if (err)
|
if (err)
|
||||||
@ -474,6 +475,7 @@ utils.encipher = function encipher(data, key, iv) {
|
|||||||
utils.decrypt = function decrypt(data, passphrase, iv, callback) {
|
utils.decrypt = function decrypt(data, passphrase, iv, callback) {
|
||||||
assert(Buffer.isBuffer(data));
|
assert(Buffer.isBuffer(data));
|
||||||
assert(passphrase, 'No passphrase.');
|
assert(passphrase, 'No passphrase.');
|
||||||
|
assert(Buffer.isBuffer(iv));
|
||||||
|
|
||||||
utils.derive(passphrase, function(err, key) {
|
utils.derive(passphrase, function(err, key) {
|
||||||
if (err)
|
if (err)
|
||||||
|
|||||||
@ -295,7 +295,7 @@ Wallet.prototype.lock = function lock() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.unlock = function unlock(passphrase, timeout, callback) {
|
Wallet.prototype.unlock = function unlock(passphrase, timeout, callback) {
|
||||||
this.master.toKey(passphrase, timeout, callback);
|
this.master.unlock(passphrase, timeout, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,7 +340,7 @@ Wallet.prototype.createAccount = function createAccount(options, callback, force
|
|||||||
|
|
||||||
callback = utils.wrap(callback, unlock);
|
callback = utils.wrap(callback, unlock);
|
||||||
|
|
||||||
this.master.toKey(options.passphrase, options.timeout, function(err, master) {
|
this.unlock(options.passphrase, options.timeout, function(err, master) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -918,19 +918,26 @@ Wallet.prototype.getRedeem = function getRedeem(hash, callback) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan for active accounts and addresses. Used for importing a wallet.
|
* Scan for active accounts and addresses. Used for importing a wallet.
|
||||||
* @param {Function} getByAddress - Must be a function which accepts
|
* @param {Function} scanner - Must be a function which accepts
|
||||||
* a {@link Base58Address} as well as a callback and returns
|
* a {@link Base58Address} as well as a callback and returns
|
||||||
* transactions by address.
|
* transactions by address.
|
||||||
* @param {Function} callback - Return [Error, Number] (total number
|
* @param {Function} callback - Return [Error, Number] (total number
|
||||||
* of addresses allocated).
|
* of addresses allocated).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Wallet.prototype.scan = function scan(getByAddress, callback) {
|
Wallet.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
var index = 0;
|
||||||
var unlock;
|
var unlock;
|
||||||
|
|
||||||
unlock = this.locker.lock(scan, [getByAddress, callback]);
|
if (typeof maxGap === 'function') {
|
||||||
|
callback = scanner;
|
||||||
|
scanner = maxGap;
|
||||||
|
maxGap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock = this.locker.lock(scan, [maxGap, scanner, callback]);
|
||||||
|
|
||||||
if (!unlock)
|
if (!unlock)
|
||||||
return;
|
return;
|
||||||
@ -940,22 +947,24 @@ Wallet.prototype.scan = function scan(getByAddress, callback) {
|
|||||||
if (!this.initialized)
|
if (!this.initialized)
|
||||||
return callback(new Error('Wallet is not initialized.'));
|
return callback(new Error('Wallet is not initialized.'));
|
||||||
|
|
||||||
(function next(err, account) {
|
(function next() {
|
||||||
if (err)
|
self.getAccount(index++, function(err, account) {
|
||||||
return callback(err);
|
|
||||||
|
|
||||||
account.scan(getByAddress, function(err, result) {
|
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (result === 0)
|
if (!account)
|
||||||
return callback(null, total);
|
return callback(null, total);
|
||||||
|
|
||||||
total += result;
|
account.scan(maxGap, scanner, function(err, result) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
|
||||||
self.createAccount(self.options, next, true);
|
total += result;
|
||||||
});
|
|
||||||
})(null, this.account);
|
next();
|
||||||
|
});
|
||||||
|
}, true);
|
||||||
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1012,7 +1021,7 @@ Wallet.prototype.sign = function sign(tx, options, callback) {
|
|||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
self.master.toKey(options.passphrase, options.timeout, function(err, master) {
|
self.unlock(options.passphrase, options.timeout, function(err, master) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
@ -1545,7 +1554,7 @@ function Account(db, options) {
|
|||||||
|
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.network = db.network;
|
this.network = db.network;
|
||||||
this.lookahead = Account.LOOKAHEAD;
|
this.lookahead = Account.MAX_LOOKAHEAD;
|
||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
@ -1636,7 +1645,14 @@ Account.fromOptions = function fromOptions(db, options) {
|
|||||||
* @const {Number}
|
* @const {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.LOOKAHEAD = 5;
|
Account.MAX_LOOKAHEAD = 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default address gap for scanning.
|
||||||
|
* @const {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Account.MAX_GAP = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to intialize the account (generating
|
* Attempt to intialize the account (generating
|
||||||
@ -2040,16 +2056,25 @@ Account.prototype.setDepth = function setDepth(receiveDepth, changeDepth, callba
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan for addresses.
|
* Scan for addresses.
|
||||||
* @param {Function} getByAddress - Must be a callback which accepts
|
* @param {Function} scanner - Must be a callback which accepts
|
||||||
* a callback and returns transactions by address.
|
* a callback and returns transactions by address.
|
||||||
* @param {Function} callback - Return [Error, Number] (total number
|
* @param {Function} callback - Return [Error, Number] (total number
|
||||||
* of addresses allocated).
|
* of addresses allocated).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Account.prototype.scan = function scan(getByAddress, callback) {
|
Account.prototype.scan = function scan(maxGap, scanner, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var total = 0;
|
var total = 0;
|
||||||
|
|
||||||
|
if (typeof maxGap === 'function') {
|
||||||
|
callback = scanner;
|
||||||
|
scanner = maxGap;
|
||||||
|
maxGap = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxGap == null)
|
||||||
|
maxGap = Account.MAX_GAP;
|
||||||
|
|
||||||
if (!this.initialized)
|
if (!this.initialized)
|
||||||
return callback(new Error('Account is not initialized.'));
|
return callback(new Error('Account is not initialized.'));
|
||||||
|
|
||||||
@ -2068,37 +2093,63 @@ Account.prototype.scan = function scan(getByAddress, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(function chainCheck(change) {
|
(function chainCheck(change) {
|
||||||
var address = change ? self.changeAddress : self.receiveAddress;
|
var depth = change ? self.changeDepth : self.receiveDepth;
|
||||||
|
var index = 0;
|
||||||
var gap = 0;
|
var gap = 0;
|
||||||
|
|
||||||
(function next(err, address) {
|
function createAddress(callback) {
|
||||||
if (err)
|
if (index === depth)
|
||||||
return callback(err);
|
return self.createAddress(change, callback);
|
||||||
|
return callback(null, self.deriveAddress(change, index++));
|
||||||
|
}
|
||||||
|
|
||||||
getByAddress(address.getAddress(), function(err, txs) {
|
(function next() {
|
||||||
|
createAddress(function(err, address) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
addTX(txs, function(err, result) {
|
scanner(address.getAddress(), function(err, txs) {
|
||||||
if (err)
|
if (err)
|
||||||
return callback(err);
|
return callback(err);
|
||||||
|
|
||||||
if (result) {
|
addTX(txs, function(err, result) {
|
||||||
total++;
|
if (err)
|
||||||
gap = 0;
|
return callback(err);
|
||||||
return self.createAddress(change, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++gap < 20)
|
// Special case for maxGap=0
|
||||||
return self.createAddress(change, next);
|
if (maxGap === 0 && index === depth) {
|
||||||
|
if (!change)
|
||||||
|
return chainCheck(true);
|
||||||
|
return callback(null, total);
|
||||||
|
}
|
||||||
|
|
||||||
if (!change)
|
if (result) {
|
||||||
return chainCheck(true);
|
total++;
|
||||||
|
gap = 0;
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
return callback(null, total);
|
if (++gap < Account.MAX_GAP)
|
||||||
|
return next();
|
||||||
|
|
||||||
|
if (!change) {
|
||||||
|
self.receiveDepth = Math.max(depth, self.receiveDepth - gap);
|
||||||
|
self.receiveAddress = self.deriveReceive(self.receiveDepth - 1);
|
||||||
|
return chainCheck(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.changeDepth = Math.max(depth, self.changeDepth - gap);
|
||||||
|
self.changeAddress = self.deriveChange(self.changeDepth - 1);
|
||||||
|
|
||||||
|
self.save(function(err) {
|
||||||
|
if (err)
|
||||||
|
return callback(err);
|
||||||
|
return callback(null, total);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})(null, address);
|
})();
|
||||||
})(false);
|
})(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2353,11 +2404,11 @@ MasterKey.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {HDPrivateKey}
|
* @returns {HDPrivateKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MasterKey.prototype.toKey = function toKey(passphrase, timeout, callback) {
|
MasterKey.prototype.unlock = function _unlock(passphrase, timeout, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var unlock;
|
var unlock;
|
||||||
|
|
||||||
unlock = this.locker.lock(toKey, [passphrase, timeout, callback]);
|
unlock = this.locker.lock(_unlock, [passphrase, timeout, callback]);
|
||||||
|
|
||||||
if (!unlock)
|
if (!unlock)
|
||||||
return;
|
return;
|
||||||
@ -2538,6 +2589,16 @@ MasterKey.prototype.toRaw = function toRaw(writer) {
|
|||||||
p.writeVarBytes(this.iv);
|
p.writeVarBytes(this.iv);
|
||||||
p.writeVarBytes(this.ciphertext);
|
p.writeVarBytes(this.ciphertext);
|
||||||
|
|
||||||
|
// Future-proofing:
|
||||||
|
// algorithm (0=pbkdf2, 1=scrypt)
|
||||||
|
p.writeU8(0);
|
||||||
|
// iterations (pbkdf2) / N (scrypt)
|
||||||
|
p.writeU32(50000);
|
||||||
|
// r (scrypt)
|
||||||
|
p.writeU32(0);
|
||||||
|
// p (scrypt)
|
||||||
|
p.writeU32(0);
|
||||||
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
p = p.render();
|
p = p.render();
|
||||||
|
|
||||||
|
|||||||
@ -1211,6 +1211,16 @@ Path.prototype.inspect = function() {
|
|||||||
+ '>';
|
+ '>';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Path.prototype.toJSON = function toJSON() {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
name: this.name,
|
||||||
|
account: this.account,
|
||||||
|
change: this.change,
|
||||||
|
index: this.index
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
Path.prototype.toRaw = function toRaw(writer) {
|
Path.prototype.toRaw = function toRaw(writer) {
|
||||||
var p = new BufferWriter(writer);
|
var p = new BufferWriter(writer);
|
||||||
|
|
||||||
|
|||||||
@ -873,6 +873,7 @@ describe('Wallet', function() {
|
|||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
w1.master.stop();
|
w1.master.stop();
|
||||||
w1.master.key = null;
|
w1.master.key = null;
|
||||||
|
utils.print(w1.toJSON());
|
||||||
|
|
||||||
// Coinbase
|
// Coinbase
|
||||||
var t1 = bcoin.mtx()
|
var t1 = bcoin.mtx()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user