wallet: optimize depth syncing.

This commit is contained in:
Christopher Jeffrey 2016-11-02 03:15:48 -07:00
parent aa79d92a83
commit 2358784d43
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
2 changed files with 119 additions and 63 deletions

View File

@ -234,7 +234,8 @@ Account.prototype.init = co(function* init() {
assert(this.nestedDepth === 0); assert(this.nestedDepth === 0);
this.initialized = true; this.initialized = true;
yield this.setDepth(1, 1, 1);
yield this.initDepth();
}); });
/** /**
@ -433,32 +434,29 @@ Account.prototype.createNested = function createNested() {
*/ */
Account.prototype.createKey = co(function* createKey(branch) { Account.prototype.createKey = co(function* createKey(branch) {
var ring, lookahead; var key, lookahead;
switch (branch) { switch (branch) {
case 0: case 0:
ring = this.deriveReceive(this.receiveDepth); key = this.deriveReceive(this.receiveDepth);
lookahead = this.deriveReceive(this.receiveDepth + this.lookahead); lookahead = this.deriveReceive(this.receiveDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead); yield this.saveKey(lookahead);
this.receiveDepth++; this.receiveDepth++;
this.receive = ring; this.receive = key;
break; break;
case 1: case 1:
ring = this.deriveChange(this.changeDepth); key = this.deriveChange(this.changeDepth);
lookahead = this.deriveChange(this.changeDepth + this.lookahead); lookahead = this.deriveChange(this.changeDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead); yield this.saveKey(lookahead);
this.changeDepth++; this.changeDepth++;
this.change = ring; this.change = key;
break; break;
case 2: case 2:
ring = this.deriveNested(this.nestedDepth); key = this.deriveNested(this.nestedDepth);
lookahead = this.deriveNested(this.nestedDepth + this.lookahead); lookahead = this.deriveNested(this.nestedDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead); yield this.saveKey(lookahead);
this.nestedDepth++; this.nestedDepth++;
this.nested = ring; this.nested = key;
break; break;
default: default:
throw new Error('Bad branch: ' + branch); throw new Error('Bad branch: ' + branch);
@ -466,7 +464,7 @@ Account.prototype.createKey = co(function* createKey(branch) {
this.save(); this.save();
return ring; return key;
}); });
/** /**
@ -608,68 +606,121 @@ Account.prototype.savePath = function savePath(path) {
}; };
/** /**
* Set change and receiving depth (depth is the index of the _next_ address). * Initialize address depths (including lookahead).
* Allocate all addresses up to depth. Note that this also allocates * @returns {Promise}
* new lookahead addresses.
* @param {Number} depth
* @returns {Promise} - Returns {@link WalletKey}, {@link WalletKey}.
*/ */
Account.prototype.setDepth = co(function* setDepth(receiveDepth, changeDepth, nestedDepth) { Account.prototype.initDepth = co(function* initDepth() {
var i = -1; var i, key;
var receive, change, nested, lookahead;
if (receiveDepth > this.receiveDepth) { // Receive Address
for (i = this.receiveDepth; i < receiveDepth; i++) { this.receive = this.deriveReceive(0);
receive = this.deriveReceive(i); this.receiveDepth = 1;
yield this.saveKey(receive);
}
for (i = receiveDepth; i < receiveDepth + this.lookahead; i++) { yield this.saveKey(this.receive);
lookahead = this.deriveReceive(i);
yield this.saveKey(lookahead);
}
this.receive = receive; // Change Address
this.receiveDepth = receiveDepth; this.change = this.deriveChange(0);
this.changeDepth = 1;
yield this.saveKey(this.change);
// Nested Address
if (this.witness) {
this.nested = this.deriveNested(0);
this.nestedDepth = 1;
yield this.saveKey(this.nested);
} }
if (changeDepth > this.changeDepth) { // Lookaheads
for (i = this.changeDepth; i < changeDepth; i++) { for (i = 0; i < this.lookahead; i++) {
change = this.deriveChange(i); key = this.deriveReceive(i + 1);
yield this.saveKey(change); yield this.saveKey(key);
}
for (i = changeDepth; i < changeDepth + this.lookahead; i++) {
lookahead = this.deriveChange(i);
yield this.saveKey(lookahead);
}
this.change = change;
this.changeDepth = changeDepth;
} }
if (this.witness && nestedDepth > this.nestedDepth) { for (i = 0; i < this.lookahead; i++) {
for (i = this.nestedDepth; i < nestedDepth; i++) { key = this.deriveChange(i + 1);
nested = this.deriveNested(i); yield this.saveKey(key);
yield this.saveKey(nested);
}
for (i = nestedDepth; i < nestedDepth + this.lookahead; i++) {
lookahead = this.deriveNested(i);
yield this.saveKey(lookahead);
}
this.nested = nested;
this.nestedDepth = nestedDepth;
} }
if (i === -1) if (this.witness) {
return; for (i = 0; i < this.lookahead; i++) {
key = this.deriveNested(i + 1);
yield this.saveKey(key);
}
}
this.save(); this.save();
});
return receive || nested; /**
* Allocate new lookahead addresses if necessary.
* @param {Number} receiveDepth
* @param {Number} changeDepth
* @param {Number} nestedDepth
* @returns {Promise} - Returns {@link WalletKey}.
*/
Account.prototype.syncDepth = co(function* syncDepth(receive, change, nested) {
var derived = false;
var result = null;
var i, depth, key;
if (receive > this.receiveDepth) {
depth = this.receiveDepth + this.lookahead;
assert(receive < depth);
for (i = depth; i < receive + this.lookahead; i++) {
key = this.deriveReceive(i);
yield this.saveKey(key);
}
this.receive = this.deriveReceive(receive - 1);
this.receiveDepth = receive;
derived = true;
result = this.receive;
}
if (change > this.changeDepth) {
depth = this.changeDepth + this.lookahead;
assert(change < depth);
for (i = depth; i < change + this.lookahead; i++) {
key = this.deriveChange(i);
yield this.saveKey(key);
}
this.change = this.deriveChange(change - 1);
this.changeDepth = change;
derived = true;
}
if (this.witness && nested > this.nestedDepth) {
depth = this.nestedDepth + this.lookahead;
assert(nested < depth);
for (i = depth; i < nested + this.lookahead; i++) {
key = this.deriveNested(i);
yield this.saveKey(key);
}
this.nested = this.deriveNested(nested - 1);
this.nestedDepth = nested;
derived = true;
result = this.nested;
}
if (derived)
this.save();
return result;
}); });
/** /**

View File

@ -1659,7 +1659,7 @@ Wallet.prototype.getKey = co(function* getKey(address) {
Wallet.prototype.getPrivateKey = co(function* getPrivateKey(address, passphrase) { Wallet.prototype.getPrivateKey = co(function* getPrivateKey(address, passphrase) {
var hash = Address.getHash(address, 'hex'); var hash = Address.getHash(address, 'hex');
var path, account; var path, account, key;
if (!hash) if (!hash)
return; return;
@ -1676,7 +1676,12 @@ Wallet.prototype.getPrivateKey = co(function* getPrivateKey(address, passphrase)
yield this.unlock(passphrase); yield this.unlock(passphrase);
return account.derivePath(path, this.master); key = account.derivePath(path, this.master);
if (!key.privateKey)
return;
return key;
}); });
/** /**
@ -1796,7 +1801,7 @@ Wallet.prototype.syncOutputDepth = co(function* syncOutputDepth(details) {
if (!account) if (!account)
continue; continue;
ring = yield account.setDepth(receive, change, nested); ring = yield account.syncDepth(receive, change, nested);
if (ring) if (ring)
derived.push(ring); derived.push(ring);