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);
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) {
var ring, lookahead;
var key, lookahead;
switch (branch) {
case 0:
ring = this.deriveReceive(this.receiveDepth);
key = this.deriveReceive(this.receiveDepth);
lookahead = this.deriveReceive(this.receiveDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead);
this.receiveDepth++;
this.receive = ring;
this.receive = key;
break;
case 1:
ring = this.deriveChange(this.changeDepth);
key = this.deriveChange(this.changeDepth);
lookahead = this.deriveChange(this.changeDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead);
this.changeDepth++;
this.change = ring;
this.change = key;
break;
case 2:
ring = this.deriveNested(this.nestedDepth);
key = this.deriveNested(this.nestedDepth);
lookahead = this.deriveNested(this.nestedDepth + this.lookahead);
yield this.saveKey(ring);
yield this.saveKey(lookahead);
this.nestedDepth++;
this.nested = ring;
this.nested = key;
break;
default:
throw new Error('Bad branch: ' + branch);
@ -466,7 +464,7 @@ Account.prototype.createKey = co(function* createKey(branch) {
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).
* Allocate all addresses up to depth. Note that this also allocates
* new lookahead addresses.
* @param {Number} depth
* @returns {Promise} - Returns {@link WalletKey}, {@link WalletKey}.
* Initialize address depths (including lookahead).
* @returns {Promise}
*/
Account.prototype.setDepth = co(function* setDepth(receiveDepth, changeDepth, nestedDepth) {
var i = -1;
var receive, change, nested, lookahead;
Account.prototype.initDepth = co(function* initDepth() {
var i, key;
if (receiveDepth > this.receiveDepth) {
for (i = this.receiveDepth; i < receiveDepth; i++) {
receive = this.deriveReceive(i);
yield this.saveKey(receive);
}
// Receive Address
this.receive = this.deriveReceive(0);
this.receiveDepth = 1;
for (i = receiveDepth; i < receiveDepth + this.lookahead; i++) {
lookahead = this.deriveReceive(i);
yield this.saveKey(lookahead);
}
yield this.saveKey(this.receive);
this.receive = receive;
this.receiveDepth = receiveDepth;
// Change Address
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) {
for (i = this.changeDepth; i < changeDepth; i++) {
change = this.deriveChange(i);
yield this.saveKey(change);
}
for (i = changeDepth; i < changeDepth + this.lookahead; i++) {
lookahead = this.deriveChange(i);
yield this.saveKey(lookahead);
}
this.change = change;
this.changeDepth = changeDepth;
// Lookaheads
for (i = 0; i < this.lookahead; i++) {
key = this.deriveReceive(i + 1);
yield this.saveKey(key);
}
if (this.witness && nestedDepth > this.nestedDepth) {
for (i = this.nestedDepth; i < nestedDepth; i++) {
nested = this.deriveNested(i);
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;
for (i = 0; i < this.lookahead; i++) {
key = this.deriveChange(i + 1);
yield this.saveKey(key);
}
if (i === -1)
return;
if (this.witness) {
for (i = 0; i < this.lookahead; i++) {
key = this.deriveNested(i + 1);
yield this.saveKey(key);
}
}
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) {
var hash = Address.getHash(address, 'hex');
var path, account;
var path, account, key;
if (!hash)
return;
@ -1676,7 +1676,12 @@ Wallet.prototype.getPrivateKey = co(function* getPrivateKey(address, 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)
continue;
ring = yield account.setDepth(receive, change, nested);
ring = yield account.syncDepth(receive, change, nested);
if (ring)
derived.push(ring);