wallet: use batches.
This commit is contained in:
parent
969fd8f704
commit
55f5ff9493
@ -11,6 +11,7 @@ const assert = require('assert');
|
||||
|
||||
const LOW = Buffer.from([0x00]);
|
||||
const HIGH = Buffer.from([0xff]);
|
||||
const DUMMY = Buffer.alloc(0);
|
||||
|
||||
let VERSION_ERROR;
|
||||
|
||||
@ -50,7 +51,6 @@ function LowlevelUp(backend, location, options) {
|
||||
|
||||
/**
|
||||
* Initialize the database.
|
||||
* @method
|
||||
* @private
|
||||
*/
|
||||
|
||||
@ -293,6 +293,19 @@ LowlevelUp.prototype.batch = function batch() {
|
||||
return new Batch(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a bucket.
|
||||
* @param {Buffer} [prefix=DUMMY]
|
||||
* @returns {Bucket}
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.bucket = function bucket(prefix) {
|
||||
if (!this.loaded)
|
||||
throw new Error('Database is closed.');
|
||||
|
||||
return new Bucket(this, this.batch(), prefix);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an iterator.
|
||||
* @param {Object} options
|
||||
@ -376,7 +389,6 @@ LowlevelUp.prototype.compactRange = function compactRange(start, end) {
|
||||
|
||||
/**
|
||||
* Test whether a key exists.
|
||||
* @method
|
||||
* @param {String} key
|
||||
* @returns {Promise} - Returns Boolean.
|
||||
*/
|
||||
@ -388,89 +400,54 @@ LowlevelUp.prototype.has = async function has(key) {
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @method
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.range = async function range(options) {
|
||||
LowlevelUp.prototype.range = function range(options) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: true
|
||||
});
|
||||
|
||||
const items = [];
|
||||
|
||||
await iter.each((key, value) => {
|
||||
if (options.parse) {
|
||||
const item = options.parse(key, value);
|
||||
if (item)
|
||||
items.push(item);
|
||||
} else {
|
||||
items.push(new IteratorItem(key, value));
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
return iter.range(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @method
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.keys = async function keys(options) {
|
||||
LowlevelUp.prototype.keys = function keys(options) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: false
|
||||
});
|
||||
|
||||
const items = [];
|
||||
|
||||
await iter.each((key) => {
|
||||
if (options.parse)
|
||||
key = options.parse(key);
|
||||
items.push(key);
|
||||
});
|
||||
|
||||
return items;
|
||||
return iter.keys(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @method
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
LowlevelUp.prototype.values = async function values(options) {
|
||||
LowlevelUp.prototype.values = function values(options) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: false,
|
||||
values: true
|
||||
});
|
||||
|
||||
const items = [];
|
||||
|
||||
await iter.each((value) => {
|
||||
if (options.parse)
|
||||
value = options.parse(value);
|
||||
items.push(value);
|
||||
});
|
||||
|
||||
return items;
|
||||
return iter.values(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dump database (for debugging).
|
||||
* @method
|
||||
* @returns {Promise} - Returns Object.
|
||||
*/
|
||||
|
||||
@ -493,7 +470,6 @@ LowlevelUp.prototype.dump = async function dump() {
|
||||
|
||||
/**
|
||||
* Write and assert a version number for the database.
|
||||
* @method
|
||||
* @param {Number} version
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -518,7 +494,6 @@ LowlevelUp.prototype.checkVersion = async function checkVersion(key, version) {
|
||||
|
||||
/**
|
||||
* Clone the database.
|
||||
* @method
|
||||
* @param {String} path
|
||||
* @returns {Promise}
|
||||
*/
|
||||
@ -631,6 +606,168 @@ Batch.prototype.clear = function clear() {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bucket
|
||||
* @constructor
|
||||
* @ignore
|
||||
* @param {LowlevelUp} db
|
||||
* @param {Batch} batch
|
||||
* @param {Buffer} [prefix=DUMMY]
|
||||
*/
|
||||
|
||||
function Bucket(db, batch, prefix, parent) {
|
||||
this.db = db;
|
||||
this.batch = batch;
|
||||
this.prefix = prefix || DUMMY;
|
||||
this.parent = parent || DUMMY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get child bucket.
|
||||
* @param {Buffer} [prefix=DUMMY]
|
||||
*/
|
||||
|
||||
Bucket.prototype.batch = function batch() {
|
||||
return new Bucket(this.db, this.batch, this.prefix, this.parent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get child bucket.
|
||||
* @param {Buffer} [prefix=DUMMY]
|
||||
*/
|
||||
|
||||
Bucket.prototype.bucket = function bucket(prefix = DUMMY) {
|
||||
const parent = this.prefix;
|
||||
const child = concat(parent, prefix);
|
||||
return new Bucket(this.db, this.batch, child, parent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get child bucket.
|
||||
* @param {Buffer} [prefix=DUMMY]
|
||||
*/
|
||||
|
||||
Bucket.prototype.up = function up() {
|
||||
return new Bucket(this.db, this.batch, this.parent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a value from the bucket.
|
||||
* @param {String|Buffer} key
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Bucket.prototype.has = function has(key) {
|
||||
return this.db.has(concat(this.prefix, key));
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a value from the bucket.
|
||||
* @param {String|Buffer} key
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Bucket.prototype.get = function get(key) {
|
||||
return this.db.get(concat(this.prefix, key));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an iterator.
|
||||
* @param {Object} options
|
||||
* @returns {Iterator}
|
||||
*/
|
||||
|
||||
Bucket.prototype.iterator = function iterator(options) {
|
||||
return new Iterator(this.db, options, this.prefix);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Bucket.prototype.range = function range(options = {}) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: true
|
||||
});
|
||||
return iter.range(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Bucket.prototype.keys = function keys(options = {}) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: true,
|
||||
values: false
|
||||
});
|
||||
return iter.keys(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Bucket.prototype.values = function values(options = {}) {
|
||||
const iter = this.iterator({
|
||||
gte: options.gte,
|
||||
lte: options.lte,
|
||||
keys: false,
|
||||
values: true
|
||||
});
|
||||
return iter.values(options.parse);
|
||||
};
|
||||
|
||||
/**
|
||||
* Write a value to the bucket.
|
||||
* @param {String|Buffer} key
|
||||
* @param {Buffer} value
|
||||
*/
|
||||
|
||||
Bucket.prototype.put = function put(key, value) {
|
||||
this.batch.put(concat(this.prefix, key), value);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete a value from the bucket.
|
||||
* @param {String|Buffer} key
|
||||
*/
|
||||
|
||||
Bucket.prototype.del = function del(key) {
|
||||
this.batch.del(concat(this.prefix, key));
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Write batch to database.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Bucket.prototype.write = function write() {
|
||||
return this.batch.write();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the batch.
|
||||
*/
|
||||
|
||||
Bucket.prototype.clear = function clear() {
|
||||
this.batch.clear();
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator
|
||||
* @constructor
|
||||
@ -639,8 +776,9 @@ Batch.prototype.clear = function clear() {
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
function Iterator(db, options) {
|
||||
this.options = new IteratorOptions(options);
|
||||
function Iterator(db, options, prefix) {
|
||||
this.prefix = prefix || DUMMY;
|
||||
this.options = new IteratorOptions(options, prefix);
|
||||
this.options.keyAsBuffer = db.options.bufferKeys;
|
||||
|
||||
this.iter = db.binding.iterator(this.options);
|
||||
@ -681,7 +819,7 @@ Iterator.prototype.each = async function each(cb) {
|
||||
await this.read();
|
||||
|
||||
while (this.cache.length > 0) {
|
||||
const key = this.cache.pop();
|
||||
const key = slice(this.prefix, this.cache.pop());
|
||||
const value = this.cache.pop();
|
||||
|
||||
let result = null;
|
||||
@ -725,7 +863,7 @@ Iterator.prototype.next = async function next() {
|
||||
}
|
||||
|
||||
if (this.cache.length > 0) {
|
||||
this.key = this.cache.pop();
|
||||
this.key = slice(this.prefix, this.cache.pop());
|
||||
this.value = this.cache.pop();
|
||||
return true;
|
||||
}
|
||||
@ -803,6 +941,64 @@ Iterator.prototype.end = function end() {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Iterator.prototype.range = async function range(parse) {
|
||||
const items = [];
|
||||
|
||||
await this.each((key, value) => {
|
||||
if (parse) {
|
||||
const item = parse(key, value);
|
||||
if (item)
|
||||
items.push(item);
|
||||
} else {
|
||||
items.push(new IteratorItem(key, value));
|
||||
}
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Iterator.prototype.keys = async function keys(parse) {
|
||||
const items = [];
|
||||
|
||||
await this.each((key) => {
|
||||
if (parse)
|
||||
key = parse(key);
|
||||
items.push(key);
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect all keys from iterator options.
|
||||
* @param {Object} options - Iterator options.
|
||||
* @returns {Promise} - Returns Array.
|
||||
*/
|
||||
|
||||
Iterator.prototype.values = async function values(parse) {
|
||||
const items = [];
|
||||
|
||||
await this.each((value) => {
|
||||
if (parse)
|
||||
value = parse(value);
|
||||
items.push(value);
|
||||
});
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator Item
|
||||
* @ignore
|
||||
@ -948,7 +1144,7 @@ LLUOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
function IteratorOptions(options) {
|
||||
function IteratorOptions(options, prefix) {
|
||||
this.gte = null;
|
||||
this.lte = null;
|
||||
this.gt = null;
|
||||
@ -964,8 +1160,7 @@ function IteratorOptions(options) {
|
||||
// Note: do not add this property.
|
||||
// this.limit = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
this.fromOptions(options || {}, prefix || DUMMY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -975,27 +1170,44 @@ function IteratorOptions(options) {
|
||||
* @returns {IteratorOptions}
|
||||
*/
|
||||
|
||||
IteratorOptions.prototype.fromOptions = function fromOptions(options) {
|
||||
IteratorOptions.prototype.fromOptions = function fromOptions(options, prefix) {
|
||||
assert(options, 'Options are required.');
|
||||
|
||||
if (options.gte != null) {
|
||||
assert(Buffer.isBuffer(options.gte) || typeof options.gte === 'string');
|
||||
this.gte = options.gte;
|
||||
this.gte = concat(prefix, options.gte);
|
||||
}
|
||||
|
||||
if (options.lte != null) {
|
||||
assert(Buffer.isBuffer(options.lte) || typeof options.lte === 'string');
|
||||
this.lte = options.lte;
|
||||
this.lte = concat(prefix, options.lte);
|
||||
}
|
||||
|
||||
if (options.gt != null) {
|
||||
assert(Buffer.isBuffer(options.gt) || typeof options.gt === 'string');
|
||||
this.gt = options.gt;
|
||||
this.gt = concat(prefix, options.gt);
|
||||
}
|
||||
|
||||
if (options.lt != null) {
|
||||
assert(Buffer.isBuffer(options.lt) || typeof options.lt === 'string');
|
||||
this.lt = options.lt;
|
||||
this.lt = concat(prefix, options.lt);
|
||||
}
|
||||
|
||||
if (prefix.length > 0) {
|
||||
if (!this.gt && !this.gte)
|
||||
this.gt = prefix;
|
||||
|
||||
if (!this.lt && !this.lte) {
|
||||
const pre = Buffer.from(prefix);
|
||||
for (let i = pre.length - 1; i >= 0; i--) {
|
||||
if (pre[i] !== 0xff) {
|
||||
pre[i] += 1;
|
||||
break;
|
||||
}
|
||||
pre[i] = 0;
|
||||
}
|
||||
this.lt = pre;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.keys != null) {
|
||||
@ -1058,6 +1270,54 @@ function wrap(resolve, reject) {
|
||||
};
|
||||
}
|
||||
|
||||
function slice(prefix, key) {
|
||||
if (!key || key.length === 0)
|
||||
return key;
|
||||
|
||||
if (prefix.length === 0)
|
||||
return key;
|
||||
|
||||
if (typeof key === 'string') {
|
||||
if (Buffer.isBuffer(prefix))
|
||||
prefix = prefix.toString('ascii');
|
||||
assert(typeof prefix === 'string');
|
||||
assert(key.length > prefix.length);
|
||||
return key.slice(prefix.length);
|
||||
}
|
||||
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length > prefix.length);
|
||||
|
||||
return key.slice(prefix.length);
|
||||
}
|
||||
|
||||
function concat(prefix, key) {
|
||||
if (prefix.length === 0)
|
||||
return key;
|
||||
|
||||
if (typeof key === 'string') {
|
||||
if (Buffer.isBuffer(prefix))
|
||||
prefix = prefix.toString('ascii');
|
||||
assert(typeof prefix === 'string');
|
||||
return prefix + key;
|
||||
}
|
||||
|
||||
assert(Buffer.isBuffer(key));
|
||||
|
||||
const data = Buffer.allocUnsafe(prefix.length + key.length);
|
||||
|
||||
if (typeof prefix === 'string') {
|
||||
data.write(prefix, 0, 'ascii');
|
||||
} else {
|
||||
assert(Buffer.isBuffer(prefix));
|
||||
prefix.copy(data, 0);
|
||||
}
|
||||
|
||||
key.copy(data, prefix.length);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
VERSION_ERROR = 'Warning:'
|
||||
+ ' Your database does not match the current database version.'
|
||||
+ ' This is likely because the database layout or serialization'
|
||||
|
||||
@ -667,13 +667,13 @@ HTTPClient.prototype.retoken = async function retoken(id, passphrase) {
|
||||
|
||||
/**
|
||||
* Change or set master key's passphrase.
|
||||
* @param {String|Buffer} passphrase
|
||||
* @param {(String|Buffer)?} old
|
||||
* @param {String|Buffer} new_
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
HTTPClient.prototype.setPassphrase = function setPassphrase(id, old, new_) {
|
||||
const body = { old: old, new: new_ };
|
||||
HTTPClient.prototype.setPassphrase = function setPassphrase(id, passphrase, old) {
|
||||
const body = { passphrase , old };
|
||||
return this._post(`/wallet/${id}/passphrase`, body);
|
||||
};
|
||||
|
||||
|
||||
@ -336,8 +336,8 @@ HTTPWallet.prototype.createNested = function createNested(account) {
|
||||
* @see Wallet#setPassphrase
|
||||
*/
|
||||
|
||||
HTTPWallet.prototype.setPassphrase = function setPassphrase(old, new_) {
|
||||
return this.client.setPassphrase(this.id, old, new_);
|
||||
HTTPWallet.prototype.setPassphrase = function setPassphrase(passphrase, old) {
|
||||
return this.client.setPassphrase(this.id, passphrase, old);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -48,7 +48,6 @@ function Account(wdb, options) {
|
||||
|
||||
this.wdb = wdb;
|
||||
this.network = wdb.network;
|
||||
this.wallet = null;
|
||||
|
||||
this.receive = null;
|
||||
this.change = null;
|
||||
@ -226,11 +225,11 @@ Account.MAX_LOOKAHEAD = 40;
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.init = async function init() {
|
||||
Account.prototype.init = async function init(b) {
|
||||
// Waiting for more keys.
|
||||
if (this.keys.length !== this.n - 1) {
|
||||
assert(!this.initialized);
|
||||
this.save();
|
||||
this.save(b);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -240,7 +239,7 @@ Account.prototype.init = async function init() {
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
await this.initDepth();
|
||||
await this.initDepth(b);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -341,7 +340,7 @@ Account.prototype.spliceKey = function spliceKey(key) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.addSharedKey = async function addSharedKey(key) {
|
||||
Account.prototype.addSharedKey = async function addSharedKey(b, key) {
|
||||
const result = this.pushKey(key);
|
||||
|
||||
if (await this.hasDuplicate()) {
|
||||
@ -350,7 +349,7 @@ Account.prototype.addSharedKey = async function addSharedKey(key) {
|
||||
}
|
||||
|
||||
// Try to initialize again.
|
||||
await this.init();
|
||||
await this.init(b);
|
||||
|
||||
return result;
|
||||
};
|
||||
@ -361,14 +360,14 @@ Account.prototype.addSharedKey = async function addSharedKey(key) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.hasDuplicate = function hasDuplicate() {
|
||||
Account.prototype.hasDuplicate = async function hasDuplicate() {
|
||||
if (this.keys.length !== this.n - 1)
|
||||
return false;
|
||||
|
||||
const ring = this.deriveReceive(0);
|
||||
const hash = ring.getScriptHash('hex');
|
||||
|
||||
return this.wallet.hasAddress(hash);
|
||||
return this.wdb.hasPath(this.wid, hash);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -378,13 +377,13 @@ Account.prototype.hasDuplicate = function hasDuplicate() {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.removeSharedKey = function removeSharedKey(key) {
|
||||
Account.prototype.removeSharedKey = function removeSharedKey(b, key) {
|
||||
const result = this.spliceKey(key);
|
||||
|
||||
if (!result)
|
||||
return false;
|
||||
|
||||
this.save();
|
||||
this.save(b);
|
||||
|
||||
return true;
|
||||
};
|
||||
@ -422,28 +421,28 @@ Account.prototype.createNested = function createNested() {
|
||||
* @returns {Promise} - Returns {@link WalletKey}.
|
||||
*/
|
||||
|
||||
Account.prototype.createKey = async function createKey(branch) {
|
||||
Account.prototype.createKey = async function createKey(b, branch) {
|
||||
let key, lookahead;
|
||||
|
||||
switch (branch) {
|
||||
case 0:
|
||||
key = this.deriveReceive(this.receiveDepth);
|
||||
lookahead = this.deriveReceive(this.receiveDepth + this.lookahead);
|
||||
await this.saveKey(lookahead);
|
||||
await this.saveKey(b, lookahead);
|
||||
this.receiveDepth++;
|
||||
this.receive = key;
|
||||
break;
|
||||
case 1:
|
||||
key = this.deriveChange(this.changeDepth);
|
||||
lookahead = this.deriveReceive(this.changeDepth + this.lookahead);
|
||||
await this.saveKey(lookahead);
|
||||
await this.saveKey(b, lookahead);
|
||||
this.changeDepth++;
|
||||
this.change = key;
|
||||
break;
|
||||
case 2:
|
||||
key = this.deriveNested(this.nestedDepth);
|
||||
lookahead = this.deriveNested(this.nestedDepth + this.lookahead);
|
||||
await this.saveKey(lookahead);
|
||||
await this.saveKey(b, lookahead);
|
||||
this.nestedDepth++;
|
||||
this.nested = key;
|
||||
break;
|
||||
@ -570,8 +569,8 @@ Account.prototype.deriveKey = function deriveKey(branch, index, master) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.save = function save() {
|
||||
return this.wdb.saveAccount(this);
|
||||
Account.prototype.save = function save(b) {
|
||||
return this.wdb.saveAccount(b, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -580,8 +579,8 @@ Account.prototype.save = function save() {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.saveKey = function saveKey(ring) {
|
||||
return this.wdb.saveKey(this.wallet, ring);
|
||||
Account.prototype.saveKey = function saveKey(b, ring) {
|
||||
return this.wdb.saveKey(b, this.wid, ring);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -590,8 +589,8 @@ Account.prototype.saveKey = function saveKey(ring) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.savePath = function savePath(path) {
|
||||
return this.wdb.savePath(this.wallet, path);
|
||||
Account.prototype.savePath = function savePath(b, path) {
|
||||
return this.wdb.savePath(b, this.wid, path);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -599,29 +598,29 @@ Account.prototype.savePath = function savePath(path) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.initDepth = async function initDepth() {
|
||||
Account.prototype.initDepth = async function initDepth(b) {
|
||||
// Receive Address
|
||||
this.receive = this.deriveReceive(0);
|
||||
this.receiveDepth = 1;
|
||||
|
||||
await this.saveKey(this.receive);
|
||||
await this.saveKey(b, this.receive);
|
||||
|
||||
// Lookahead
|
||||
for (let i = 0; i < this.lookahead; i++) {
|
||||
const key = this.deriveReceive(i + 1);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
|
||||
// Change Address
|
||||
this.change = this.deriveChange(0);
|
||||
this.changeDepth = 1;
|
||||
|
||||
await this.saveKey(this.change);
|
||||
await this.saveKey(b, this.change);
|
||||
|
||||
// Lookahead
|
||||
for (let i = 0; i < this.lookahead; i++) {
|
||||
const key = this.deriveChange(i + 1);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
|
||||
// Nested Address
|
||||
@ -629,16 +628,16 @@ Account.prototype.initDepth = async function initDepth() {
|
||||
this.nested = this.deriveNested(0);
|
||||
this.nestedDepth = 1;
|
||||
|
||||
await this.saveKey(this.nested);
|
||||
await this.saveKey(b, this.nested);
|
||||
|
||||
// Lookahead
|
||||
for (let i = 0; i < this.lookahead; i++) {
|
||||
const key = this.deriveNested(i + 1);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
}
|
||||
|
||||
this.save();
|
||||
this.save(b);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -649,7 +648,7 @@ Account.prototype.initDepth = async function initDepth() {
|
||||
* @returns {Promise} - Returns {@link WalletKey}.
|
||||
*/
|
||||
|
||||
Account.prototype.syncDepth = async function syncDepth(receive, change, nested) {
|
||||
Account.prototype.syncDepth = async function syncDepth(b, receive, change, nested) {
|
||||
let derived = false;
|
||||
let result = null;
|
||||
|
||||
@ -660,7 +659,7 @@ Account.prototype.syncDepth = async function syncDepth(receive, change, nested)
|
||||
|
||||
for (let i = depth; i < receive + this.lookahead; i++) {
|
||||
const key = this.deriveReceive(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
|
||||
this.receive = this.deriveReceive(receive - 1);
|
||||
@ -677,7 +676,7 @@ Account.prototype.syncDepth = async function syncDepth(receive, change, nested)
|
||||
|
||||
for (let i = depth; i < change + this.lookahead; i++) {
|
||||
const key = this.deriveChange(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
|
||||
this.change = this.deriveChange(change - 1);
|
||||
@ -693,7 +692,7 @@ Account.prototype.syncDepth = async function syncDepth(receive, change, nested)
|
||||
|
||||
for (let i = depth; i < nested + this.lookahead; i++) {
|
||||
const key = this.deriveNested(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
|
||||
this.nested = this.deriveNested(nested - 1);
|
||||
@ -704,7 +703,7 @@ Account.prototype.syncDepth = async function syncDepth(receive, change, nested)
|
||||
}
|
||||
|
||||
if (derived)
|
||||
this.save();
|
||||
this.save(b);
|
||||
|
||||
return result;
|
||||
};
|
||||
@ -715,13 +714,9 @@ Account.prototype.syncDepth = async function syncDepth(receive, change, nested)
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Account.prototype.setLookahead = async function setLookahead(lookahead) {
|
||||
if (lookahead === this.lookahead) {
|
||||
this.wdb.logger.warning(
|
||||
'Lookahead is not changing for: %s/%s.',
|
||||
this.id, this.name);
|
||||
Account.prototype.setLookahead = async function setLookahead(b, lookahead) {
|
||||
if (lookahead === this.lookahead)
|
||||
return;
|
||||
}
|
||||
|
||||
if (lookahead < this.lookahead) {
|
||||
const diff = this.lookahead - lookahead;
|
||||
@ -739,7 +734,7 @@ Account.prototype.setLookahead = async function setLookahead(lookahead) {
|
||||
|
||||
this.lookahead = lookahead;
|
||||
|
||||
this.save();
|
||||
this.save(b);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -750,7 +745,7 @@ Account.prototype.setLookahead = async function setLookahead(lookahead) {
|
||||
|
||||
for (let i = depth; i < target; i++) {
|
||||
const key = this.deriveReceive(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -760,7 +755,7 @@ Account.prototype.setLookahead = async function setLookahead(lookahead) {
|
||||
|
||||
for (let i = depth; i < target; i++) {
|
||||
const key = this.deriveChange(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,12 +765,12 @@ Account.prototype.setLookahead = async function setLookahead(lookahead) {
|
||||
|
||||
for (let i = depth; i < target; i++) {
|
||||
const key = this.deriveNested(i);
|
||||
await this.saveKey(key);
|
||||
await this.saveKey(b, key);
|
||||
}
|
||||
}
|
||||
|
||||
this.lookahead = lookahead;
|
||||
this.save();
|
||||
this.save(b);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -305,12 +305,12 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
// Change passphrase
|
||||
this.post('/:id/passphrase', async (req, res) => {
|
||||
const valid = req.valid();
|
||||
const passphrase = valid.str('passphrase');
|
||||
const old = valid.str('old');
|
||||
const new_ = valid.str('new');
|
||||
|
||||
enforce(old || new_, 'Passphrase is required.');
|
||||
|
||||
await req.wallet.setPassphrase(old, new_);
|
||||
await req.wallet.setPassphrase(passphrase, old);
|
||||
|
||||
res.send(200, { success: true });
|
||||
});
|
||||
@ -416,7 +416,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
|
||||
const details = await req.wallet.getDetails(tx.hash('hex'));
|
||||
|
||||
res.send(200, details.toJSON());
|
||||
res.send(200, details.toJSON(this.network));
|
||||
});
|
||||
|
||||
// Create TX
|
||||
@ -790,7 +790,7 @@ HTTPServer.prototype.initRouter = function initRouter() {
|
||||
|
||||
const details = await req.wallet.toDetails(tx);
|
||||
|
||||
res.send(200, details.toJSON());
|
||||
res.send(200, details.toJSON(this.network));
|
||||
});
|
||||
|
||||
// Resend
|
||||
@ -813,38 +813,38 @@ HTTPServer.prototype.initSockets = function initSockets() {
|
||||
this.handleSocket(socket);
|
||||
});
|
||||
|
||||
this.walletdb.on('tx', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
this.to(`w:${id}`, 'wallet tx', json);
|
||||
this.walletdb.on('tx', (w, tx, details) => {
|
||||
const json = details.toJSON(this.network);
|
||||
this.to(`w:${w.id}`, 'wallet tx', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('confirmed', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
this.to(`w:${id}`, 'wallet confirmed', json);
|
||||
this.walletdb.on('confirmed', (w, tx, details) => {
|
||||
const json = details.toJSON(this.network);
|
||||
this.to(`w:${w.id}`, 'wallet confirmed', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('unconfirmed', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
this.to(`w:${id}`, 'wallet unconfirmed', json);
|
||||
this.walletdb.on('unconfirmed', (w, tx, details) => {
|
||||
const json = details.toJSON(this.network);
|
||||
this.to(`w:${w.id}`, 'wallet unconfirmed', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('conflict', (id, tx, details) => {
|
||||
const json = details.toJSON();
|
||||
this.to(`w:${id}`, 'wallet conflict', json);
|
||||
this.walletdb.on('conflict', (w, tx, details) => {
|
||||
const json = details.toJSON(this.network);
|
||||
this.to(`w:${w.id}`, 'wallet conflict', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('balance', (id, balance) => {
|
||||
this.walletdb.on('balance', (w, balance) => {
|
||||
const json = balance.toJSON();
|
||||
this.to(`w:${id}`, 'wallet balance', json);
|
||||
this.to(`w:${w.id}`, 'wallet balance', json);
|
||||
});
|
||||
|
||||
this.walletdb.on('address', (id, receive) => {
|
||||
this.walletdb.on('address', (w, receive) => {
|
||||
const json = [];
|
||||
|
||||
for (const addr of receive)
|
||||
json.push(addr.toJSON());
|
||||
|
||||
this.to(`w:${id}`, 'wallet address', json);
|
||||
this.to(`w:${w.id}`, 'wallet address', json);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -95,13 +95,8 @@ layouts.walletdb = {
|
||||
|
||||
layouts.txdb = {
|
||||
binary: false,
|
||||
prefix: function prefix(wid, key) {
|
||||
assert(typeof key === 'string');
|
||||
return 't' + pad32(wid) + key;
|
||||
},
|
||||
pre: function pre(key) {
|
||||
assert(typeof key === 'string');
|
||||
return parseInt(key.slice(1, 11), 10);
|
||||
prefix: function prefix(wid) {
|
||||
return 't' + pad32(wid);
|
||||
},
|
||||
R: 'R',
|
||||
hi: function hi(ch, hash, index) {
|
||||
@ -110,8 +105,7 @@ layouts.txdb = {
|
||||
},
|
||||
hii: function hii(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return [key.slice(0, 64), parseInt(key.slice(64), 10)];
|
||||
return [key.slice(1, 65), parseInt(key.slice(65), 10)];
|
||||
},
|
||||
ih: function ih(ch, index, hash) {
|
||||
assert(typeof hash === 'string');
|
||||
@ -119,8 +113,7 @@ layouts.txdb = {
|
||||
},
|
||||
ihh: function ihh(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return [parseInt(key.slice(0, 10), 10), key.slice(10)];
|
||||
return [parseInt(key.slice(1, 11), 10), key.slice(11)];
|
||||
},
|
||||
iih: function iih(ch, index, num, hash) {
|
||||
assert(typeof hash === 'string');
|
||||
@ -128,11 +121,10 @@ layouts.txdb = {
|
||||
},
|
||||
iihh: function iihh(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return [
|
||||
parseInt(key.slice(0, 10), 10),
|
||||
parseInt(key.slice(10, 20), 10),
|
||||
key.slice(20)
|
||||
parseInt(key.slice(1, 11), 10),
|
||||
parseInt(key.slice(11, 21), 10),
|
||||
key.slice(21)
|
||||
];
|
||||
},
|
||||
ihi: function ihi(ch, index, hash, num) {
|
||||
@ -141,11 +133,10 @@ layouts.txdb = {
|
||||
},
|
||||
ihii: function ihii(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return [
|
||||
parseInt(key.slice(0, 10), 10),
|
||||
key.slice(10, 74),
|
||||
parseInt(key.slice(74), 10)
|
||||
parseInt(key.slice(1, 11), 10),
|
||||
key.slice(11, 75),
|
||||
parseInt(key.slice(75), 10)
|
||||
];
|
||||
},
|
||||
ha: function ha(ch, hash) {
|
||||
@ -154,8 +145,7 @@ layouts.txdb = {
|
||||
},
|
||||
haa: function haa(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return key;
|
||||
return key.slice(1);
|
||||
},
|
||||
t: function t(hash) {
|
||||
return this.ha('t', hash);
|
||||
@ -235,15 +225,11 @@ layouts.txdb = {
|
||||
Cc: function Cc(key) {
|
||||
return this.ihii(key);
|
||||
},
|
||||
r: function r(hash) {
|
||||
return this.ha('r', hash);
|
||||
},
|
||||
b: function b(height) {
|
||||
return 'b' + pad32(height);
|
||||
},
|
||||
bb: function bb(key) {
|
||||
assert(typeof key === 'string');
|
||||
key = key.slice(12);
|
||||
return parseInt(key.slice(0), 10);
|
||||
return parseInt(key.slice(1), 10);
|
||||
}
|
||||
};
|
||||
|
||||
@ -199,20 +199,13 @@ layouts.walletdb = {
|
||||
|
||||
layouts.txdb = {
|
||||
binary: true,
|
||||
prefix: function prefix(wid, key) {
|
||||
prefix: function prefix(wid) {
|
||||
assert(typeof wid === 'number');
|
||||
assert(Buffer.isBuffer(key));
|
||||
const out = Buffer.allocUnsafe(5 + key.length);
|
||||
const out = Buffer.allocUnsafe(5);
|
||||
out[0] = 0x74;
|
||||
out.writeUInt32BE(wid, 1);
|
||||
key.copy(out, 5);
|
||||
return out;
|
||||
},
|
||||
pre: function pre(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length >= 5);
|
||||
return key.readUInt32BE(1, true);
|
||||
},
|
||||
R: Buffer.from([0x52]),
|
||||
hi: function hi(ch, hash, index) {
|
||||
assert(typeof hash === 'string');
|
||||
@ -225,9 +218,8 @@ layouts.txdb = {
|
||||
},
|
||||
hii: function hii(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 37);
|
||||
key = key.slice(6);
|
||||
return [key.toString('hex', 0, 32), key.readUInt32BE(32, true)];
|
||||
assert(key.length === 37);
|
||||
return [key.toString('hex', 1, 33), key.readUInt32BE(33, true)];
|
||||
},
|
||||
ih: function ih(ch, index, hash) {
|
||||
assert(typeof index === 'number');
|
||||
@ -240,9 +232,8 @@ layouts.txdb = {
|
||||
},
|
||||
ihh: function ihh(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 37);
|
||||
key = key.slice(6);
|
||||
return [key.readUInt32BE(0, true), key.toString('hex', 4, 36)];
|
||||
assert(key.length === 37);
|
||||
return [key.readUInt32BE(1, true), key.toString('hex', 5, 37)];
|
||||
},
|
||||
iih: function iih(ch, index, num, hash) {
|
||||
assert(typeof index === 'number');
|
||||
@ -257,12 +248,11 @@ layouts.txdb = {
|
||||
},
|
||||
iihh: function iihh(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 41);
|
||||
key = key.slice(6);
|
||||
assert(key.length === 41);
|
||||
return [
|
||||
key.readUInt32BE(0, true),
|
||||
key.readUInt32BE(4, true),
|
||||
key.toString('hex', 8, 40)
|
||||
key.readUInt32BE(1, true),
|
||||
key.readUInt32BE(5, true),
|
||||
key.toString('hex', 9, 41)
|
||||
];
|
||||
},
|
||||
ihi: function ihi(ch, index, hash, num) {
|
||||
@ -278,12 +268,11 @@ layouts.txdb = {
|
||||
},
|
||||
ihii: function ihii(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 41);
|
||||
key = key.slice(6);
|
||||
assert(key.length === 41);
|
||||
return [
|
||||
key.readUInt32BE(0, true),
|
||||
key.toString('hex', 4, 36),
|
||||
key.readUInt32BE(36, true)
|
||||
key.readUInt32BE(1, true),
|
||||
key.toString('hex', 5, 37),
|
||||
key.readUInt32BE(37, true)
|
||||
];
|
||||
},
|
||||
ha: function ha(ch, hash) {
|
||||
@ -295,9 +284,8 @@ layouts.txdb = {
|
||||
},
|
||||
haa: function haa(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 33);
|
||||
key = key.slice(6);
|
||||
return key.toString('hex', 0);
|
||||
assert(key.length === 33);
|
||||
return key.toString('hex', 1, 33);
|
||||
},
|
||||
t: function t(hash) {
|
||||
return this.ha(0x74, hash);
|
||||
@ -371,9 +359,6 @@ layouts.txdb = {
|
||||
Cc: function Cc(key) {
|
||||
return this.ihii(key);
|
||||
},
|
||||
r: function r(hash) {
|
||||
return this.ha(0x72, hash);
|
||||
},
|
||||
b: function b(height) {
|
||||
assert(typeof height === 'number');
|
||||
const key = Buffer.allocUnsafe(5);
|
||||
@ -383,8 +368,7 @@ layouts.txdb = {
|
||||
},
|
||||
bb: function bb(key) {
|
||||
assert(Buffer.isBuffer(key));
|
||||
assert(key.length - 5 === 5);
|
||||
key = key.slice(6);
|
||||
return key.readUInt32BE(0, true);
|
||||
assert(key.length === 5);
|
||||
return key.readUInt32BE(1, true);
|
||||
}
|
||||
};
|
||||
|
||||
@ -316,7 +316,7 @@ RPC.prototype.encryptWallet = async function encryptWallet(args, help) {
|
||||
throw new RPCError(errs.MISC_ERROR, 'encryptwallet "passphrase"');
|
||||
|
||||
try {
|
||||
await wallet.setPassphrase(passphrase);
|
||||
await wallet.encrypt(passphrase);
|
||||
} catch (e) {
|
||||
throw new RPCError(errs.WALLET_ENCRYPTION_FAILED, 'Encryption failed.');
|
||||
}
|
||||
@ -1432,15 +1432,15 @@ RPC.prototype.walletPassphraseChange = async function walletPassphraseChange(arg
|
||||
|
||||
const valid = new Validator([args]);
|
||||
const old = valid.str(0, '');
|
||||
const new_ = valid.str(1, '');
|
||||
const passphrase = valid.str(1, '');
|
||||
|
||||
if (!wallet.master.encrypted)
|
||||
throw new RPCError(errs.WALLET_WRONG_ENC_STATE, 'Wallet is not encrypted.');
|
||||
|
||||
if (old.length < 1 || new_.length < 1)
|
||||
if (old.length < 1 || passphrase.length < 1)
|
||||
throw new RPCError(errs.INVALID_PARAMETER, 'Invalid parameter');
|
||||
|
||||
await wallet.setPassphrase(old, new_);
|
||||
await wallet.setPassphrase(passphrase, old);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,6 @@ const HD = require('../hd/hd');
|
||||
const Output = require('../primitives/output');
|
||||
const Account = require('./account');
|
||||
const MasterKey = require('./masterkey');
|
||||
const LRU = require('../utils/lru');
|
||||
const policy = require('../protocol/policy');
|
||||
const consensus = require('../protocol/consensus');
|
||||
const Mnemonic = HD.Mnemonic;
|
||||
@ -70,15 +69,11 @@ function Wallet(wdb, options) {
|
||||
assert(wdb, 'WDB required.');
|
||||
|
||||
this.wdb = wdb;
|
||||
this.db = wdb.db;
|
||||
this.network = wdb.network;
|
||||
this.logger = wdb.logger;
|
||||
this.readLock = new MappedLock();
|
||||
this.writeLock = new Lock();
|
||||
this.fundLock = new Lock();
|
||||
this.indexCache = new LRU(1000);
|
||||
this.accountCache = new LRU(1000);
|
||||
this.pathCache = new LRU(1000);
|
||||
this.current = null;
|
||||
|
||||
this.wid = 0;
|
||||
this.id = null;
|
||||
@ -89,7 +84,7 @@ function Wallet(wdb, options) {
|
||||
this.tokenDepth = 0;
|
||||
this.master = new MasterKey();
|
||||
|
||||
this.txdb = new TXDB(this);
|
||||
this.txdb = new TXDB(this.wdb);
|
||||
this.account = null;
|
||||
|
||||
if (options)
|
||||
@ -207,7 +202,7 @@ Wallet.prototype.init = async function init(options) {
|
||||
|
||||
this.logger.info('Wallet initialized (%s).', this.id);
|
||||
|
||||
await this.txdb.open();
|
||||
await this.txdb.open(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -227,7 +222,7 @@ Wallet.prototype.open = async function open() {
|
||||
|
||||
this.logger.info('Wallet opened (%s).', this.id);
|
||||
|
||||
await this.txdb.open();
|
||||
await this.txdb.open(this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -239,9 +234,7 @@ Wallet.prototype.destroy = async function destroy() {
|
||||
const unlock1 = await this.writeLock.lock();
|
||||
const unlock2 = await this.fundLock.lock();
|
||||
try {
|
||||
this.wdb.unregister(this);
|
||||
await this.master.destroy();
|
||||
this.readLock.destroy();
|
||||
this.writeLock.destroy();
|
||||
this.fundLock.destroy();
|
||||
} finally {
|
||||
@ -276,30 +269,14 @@ Wallet.prototype.addSharedKey = async function addSharedKey(acct, key) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._addSharedKey = async function _addSharedKey(acct, key) {
|
||||
if (!key) {
|
||||
key = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
const account = await this.getAccount(acct);
|
||||
|
||||
if (!account)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
this.start();
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await account.addSharedKey(key);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
const b = this.db.batch();
|
||||
const result = await account.addSharedKey(b, key);
|
||||
await b.write();
|
||||
|
||||
return result;
|
||||
};
|
||||
@ -329,47 +306,30 @@ Wallet.prototype.removeSharedKey = async function removeSharedKey(acct, key) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._removeSharedKey = async function _removeSharedKey(acct, key) {
|
||||
if (!key) {
|
||||
key = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
const account = await this.getAccount(acct);
|
||||
|
||||
if (!account)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
this.start();
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await account.removeSharedKey(key);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
const b = this.db.batch();
|
||||
const result = await account.removeSharedKey(b, key);
|
||||
await b.write();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Change or set master key's passphrase.
|
||||
* @param {(String|Buffer)?} old
|
||||
* @param {String|Buffer} new_
|
||||
* @param {String|Buffer} passphrase
|
||||
* @param {String|Buffer} old
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.setPassphrase = async function setPassphrase(old, new_) {
|
||||
if (old)
|
||||
Wallet.prototype.setPassphrase = async function setPassphrase(passphrase, old) {
|
||||
if (old != null)
|
||||
await this.decrypt(old);
|
||||
|
||||
if (new_)
|
||||
await this.encrypt(new_);
|
||||
await this.encrypt(passphrase);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -396,22 +356,17 @@ Wallet.prototype.encrypt = async function encrypt(passphrase) {
|
||||
|
||||
Wallet.prototype._encrypt = async function _encrypt(passphrase) {
|
||||
const key = await this.master.encrypt(passphrase, true);
|
||||
|
||||
this.start();
|
||||
const b = this.db.batch();
|
||||
|
||||
try {
|
||||
await this.wdb.encryptKeys(this, key);
|
||||
} catch (e) {
|
||||
await this.wdb.encryptKeys(b, this.wid, key);
|
||||
} finally {
|
||||
cleanse(key);
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
cleanse(key);
|
||||
this.save(b);
|
||||
|
||||
this.save();
|
||||
|
||||
await this.commit();
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -438,22 +393,17 @@ Wallet.prototype.decrypt = async function decrypt(passphrase) {
|
||||
|
||||
Wallet.prototype._decrypt = async function _decrypt(passphrase) {
|
||||
const key = await this.master.decrypt(passphrase, true);
|
||||
|
||||
this.start();
|
||||
const b = this.db.batch();
|
||||
|
||||
try {
|
||||
await this.wdb.decryptKeys(this, key);
|
||||
} catch (e) {
|
||||
await this.wdb.decryptKeys(b, this.wid, key);
|
||||
} finally {
|
||||
cleanse(key);
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
cleanse(key);
|
||||
this.save(b);
|
||||
|
||||
this.save();
|
||||
|
||||
await this.commit();
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -479,15 +429,16 @@ Wallet.prototype.retoken = async function retoken(passphrase) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._retoken = async function _retoken(passphrase) {
|
||||
await this.unlock(passphrase);
|
||||
if (passphrase)
|
||||
await this.unlock(passphrase);
|
||||
|
||||
this.tokenDepth++;
|
||||
this.tokenDepth += 1;
|
||||
this.token = this.getToken(this.tokenDepth);
|
||||
|
||||
this.start();
|
||||
this.save();
|
||||
const b = this.db.batch();
|
||||
this.save(b);
|
||||
|
||||
await this.commit();
|
||||
await b.write();
|
||||
|
||||
return this.token;
|
||||
};
|
||||
@ -546,24 +497,11 @@ Wallet.prototype._renameAccount = async function _renameAccount(acct, name) {
|
||||
if (await this.hasAccount(name))
|
||||
throw new Error('Account name not available.');
|
||||
|
||||
const old = account.name;
|
||||
const b = this.db.batch();
|
||||
|
||||
this.start();
|
||||
this.wdb.renameAccount(b, account, name);
|
||||
|
||||
this.wdb.renameAccount(account, name);
|
||||
|
||||
await this.commit();
|
||||
|
||||
this.indexCache.remove(old);
|
||||
|
||||
const paths = this.pathCache.values();
|
||||
|
||||
for (const path of paths) {
|
||||
if (path.account !== account.accountIndex)
|
||||
continue;
|
||||
|
||||
path.name = name;
|
||||
}
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -631,7 +569,8 @@ Wallet.prototype.getID = function getID() {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getToken = function getToken(nonce) {
|
||||
assert(this.master.key, 'Cannot derive token.');
|
||||
if (!this.master.key)
|
||||
throw new Error('Cannot derive token.');
|
||||
|
||||
const key = this.master.key.derive(44, true);
|
||||
|
||||
@ -706,17 +645,11 @@ Wallet.prototype._createAccount = async function _createAccount(options, passphr
|
||||
keys: options.keys
|
||||
};
|
||||
|
||||
this.start();
|
||||
const b = this.db.batch();
|
||||
|
||||
let account;
|
||||
try {
|
||||
account = Account.fromOptions(this.wdb, opt);
|
||||
account.wallet = this;
|
||||
await account.init();
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
const account = Account.fromOptions(this.wdb, opt);
|
||||
|
||||
await account.init(b);
|
||||
|
||||
this.logger.info('Created account %s/%s/%d.',
|
||||
account.id,
|
||||
@ -724,9 +657,9 @@ Wallet.prototype._createAccount = async function _createAccount(options, passphr
|
||||
account.accountIndex);
|
||||
|
||||
this.accountDepth++;
|
||||
this.save();
|
||||
this.save(b);
|
||||
|
||||
await this.commit();
|
||||
await b.write();
|
||||
|
||||
return account;
|
||||
};
|
||||
@ -775,7 +708,11 @@ Wallet.prototype.getAddressHashes = function getAddressHashes(acct) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccountHashes = async function getAccountHashes(acct) {
|
||||
const index = await this.ensureIndex(acct, true);
|
||||
const index = await this.getAccountIndex(acct);
|
||||
|
||||
if (index === -1)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
return await this.wdb.getAccountHashes(this.wid, index);
|
||||
};
|
||||
|
||||
@ -796,69 +733,51 @@ Wallet.prototype.getAccount = async function getAccount(acct) {
|
||||
if (index === -1)
|
||||
return null;
|
||||
|
||||
const unlock = await this.readLock.lock(index);
|
||||
|
||||
try {
|
||||
return await this._getAccount(index);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve an account from the database without a lock.
|
||||
* @param {Number} index
|
||||
* @returns {Promise} - Returns {@link Account}.
|
||||
*/
|
||||
|
||||
Wallet.prototype._getAccount = async function _getAccount(index) {
|
||||
const cache = this.accountCache.get(index);
|
||||
|
||||
if (cache)
|
||||
return cache;
|
||||
|
||||
const account = await this.wdb.getAccount(this.wid, index);
|
||||
|
||||
if (!account)
|
||||
return null;
|
||||
|
||||
account.wallet = this;
|
||||
account.wid = this.wid;
|
||||
account.id = this.id;
|
||||
account.watchOnly = this.watchOnly;
|
||||
|
||||
await account.open();
|
||||
|
||||
this.accountCache.set(index, account);
|
||||
|
||||
return account;
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup the corresponding account name's index.
|
||||
* @param {WalletID} wid
|
||||
* @param {String|Number} name - Account name/index.
|
||||
* @param {String|Number} acct - Account name/index.
|
||||
* @returns {Promise} - Returns Number.
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccountIndex = async function getAccountIndex(name) {
|
||||
if (name == null)
|
||||
Wallet.prototype.getAccountIndex = function getAccountIndex(acct) {
|
||||
if (acct == null)
|
||||
return -1;
|
||||
|
||||
if (typeof name === 'number')
|
||||
return name;
|
||||
if (typeof acct === 'number')
|
||||
return acct;
|
||||
|
||||
const cache = this.indexCache.get(name);
|
||||
return this.wdb.getAccountIndex(this.wid, acct);
|
||||
};
|
||||
|
||||
if (cache != null)
|
||||
return cache;
|
||||
/**
|
||||
* Lookup the corresponding account name's index.
|
||||
* @param {String|Number} acct - Account name/index.
|
||||
* @returns {Promise} - Returns Number.
|
||||
* @throws on non-existent account
|
||||
*/
|
||||
|
||||
const index = await this.wdb.getAccountIndex(this.wid, name);
|
||||
Wallet.prototype.ensureIndex = async function ensureIndex(acct) {
|
||||
if (acct == null || acct === -1)
|
||||
return -1;
|
||||
|
||||
const index = await this.getAccountIndex(acct);
|
||||
|
||||
if (index === -1)
|
||||
return -1;
|
||||
|
||||
this.indexCache.set(name, index);
|
||||
throw new Error('Account not found.');
|
||||
|
||||
return index;
|
||||
};
|
||||
@ -874,11 +793,6 @@ Wallet.prototype.getAccountName = async function getAccountName(index) {
|
||||
if (typeof index === 'string')
|
||||
return index;
|
||||
|
||||
const account = this.accountCache.get(index);
|
||||
|
||||
if (account)
|
||||
return account.name;
|
||||
|
||||
return await this.wdb.getAccountName(this.wid, index);
|
||||
};
|
||||
|
||||
@ -894,9 +808,6 @@ Wallet.prototype.hasAccount = async function hasAccount(acct) {
|
||||
if (index === -1)
|
||||
return false;
|
||||
|
||||
if (this.accountCache.has(index))
|
||||
return true;
|
||||
|
||||
return await this.db.hasAccount(this.wid, index);
|
||||
};
|
||||
|
||||
@ -906,7 +817,7 @@ Wallet.prototype.hasAccount = async function hasAccount(acct) {
|
||||
* @returns {Promise} - Returns {@link WalletKey}.
|
||||
*/
|
||||
|
||||
Wallet.prototype.createReceive = function createReceive(acct) {
|
||||
Wallet.prototype.createReceive = function createReceive(acct = 0) {
|
||||
return this.createKey(acct, 0);
|
||||
};
|
||||
|
||||
@ -916,7 +827,7 @@ Wallet.prototype.createReceive = function createReceive(acct) {
|
||||
* @returns {Promise} - Returns {@link WalletKey}.
|
||||
*/
|
||||
|
||||
Wallet.prototype.createChange = function createChange(acct) {
|
||||
Wallet.prototype.createChange = function createChange(acct = 0) {
|
||||
return this.createKey(acct, 1);
|
||||
};
|
||||
|
||||
@ -926,7 +837,7 @@ Wallet.prototype.createChange = function createChange(acct) {
|
||||
* @returns {Promise} - Returns {@link WalletKey}.
|
||||
*/
|
||||
|
||||
Wallet.prototype.createNested = function createNested(acct) {
|
||||
Wallet.prototype.createNested = function createNested(acct = 0) {
|
||||
return this.createKey(acct, 2);
|
||||
};
|
||||
|
||||
@ -955,32 +866,16 @@ Wallet.prototype.createKey = async function createKey(acct, branch) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._createKey = async function _createKey(acct, branch) {
|
||||
if (branch == null) {
|
||||
branch = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
const account = await this.getAccount(acct);
|
||||
|
||||
if (!account)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
this.start();
|
||||
const b = this.db.batch();
|
||||
const key = await account.createKey(b, branch);
|
||||
await b.write();
|
||||
|
||||
let result;
|
||||
try {
|
||||
result = await account.createKey(branch);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
|
||||
return result;
|
||||
return key;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -989,44 +884,8 @@ Wallet.prototype._createKey = async function _createKey(acct, branch) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.save = function save() {
|
||||
return this.wdb.save(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Start batch.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Wallet.prototype.start = function start() {
|
||||
return this.wdb.start(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop batch.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Wallet.prototype.drop = function drop() {
|
||||
return this.wdb.drop(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear batch.
|
||||
* @private
|
||||
*/
|
||||
|
||||
Wallet.prototype.clear = function clear() {
|
||||
return this.wdb.clear(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save batch.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.commit = function commit() {
|
||||
return this.wdb.commit(this);
|
||||
Wallet.prototype.save = function save(b) {
|
||||
return this.wdb.save(b, this);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1048,18 +907,8 @@ Wallet.prototype.hasAddress = async function hasAddress(address) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getPath = async function getPath(address) {
|
||||
const path = await this.readPath(address);
|
||||
|
||||
if (!path)
|
||||
return null;
|
||||
|
||||
path.name = await this.getAccountName(path.account);
|
||||
|
||||
assert(path.name);
|
||||
|
||||
this.pathCache.set(path.hash, path);
|
||||
|
||||
return path;
|
||||
const hash = Address.getHash(address, 'hex');
|
||||
return this.wdb.getPath(this.wid, this.id, hash);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1071,19 +920,7 @@ Wallet.prototype.getPath = async function getPath(address) {
|
||||
|
||||
Wallet.prototype.readPath = async function readPath(address) {
|
||||
const hash = Address.getHash(address, 'hex');
|
||||
const cache = this.pathCache.get(hash);
|
||||
|
||||
if (cache)
|
||||
return cache;
|
||||
|
||||
const path = await this.wdb.getPath(this.wid, hash);
|
||||
|
||||
if (!path)
|
||||
return null;
|
||||
|
||||
path.id = this.id;
|
||||
|
||||
return path;
|
||||
return this.wdb.readPath(this.wid, this.id, hash);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1094,10 +931,6 @@ Wallet.prototype.readPath = async function readPath(address) {
|
||||
|
||||
Wallet.prototype.hasPath = async function hasPath(address) {
|
||||
const hash = Address.getHash(address, 'hex');
|
||||
|
||||
if (this.pathCache.has(hash))
|
||||
return true;
|
||||
|
||||
return await this.wdb.hasPath(this.wid, hash);
|
||||
};
|
||||
|
||||
@ -1120,8 +953,6 @@ Wallet.prototype.getPaths = async function getPaths(acct) {
|
||||
|
||||
assert(path.name);
|
||||
|
||||
this.pathCache.set(path.hash, path);
|
||||
|
||||
result.push(path);
|
||||
}
|
||||
|
||||
@ -1135,7 +966,11 @@ Wallet.prototype.getPaths = async function getPaths(acct) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getAccountPaths = async function getAccountPaths(acct) {
|
||||
const index = await this.ensureIndex(acct, true);
|
||||
const index = await this.getAccountIndex(acct);
|
||||
|
||||
if (index === -1)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
const hashes = await this.getAccountHashes(index);
|
||||
const name = await this.getAccountName(acct);
|
||||
|
||||
@ -1151,8 +986,6 @@ Wallet.prototype.getAccountPaths = async function getAccountPaths(acct) {
|
||||
|
||||
path.name = name;
|
||||
|
||||
this.pathCache.set(path.hash, path);
|
||||
|
||||
result.push(path);
|
||||
}
|
||||
|
||||
@ -1187,15 +1020,6 @@ Wallet.prototype.importKey = async function importKey(acct, ring, passphrase) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._importKey = async function _importKey(acct, ring, passphrase) {
|
||||
if (acct && typeof acct === 'object') {
|
||||
passphrase = ring;
|
||||
ring = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
assert(ring.network === this.network,
|
||||
'Network mismatch for key.');
|
||||
|
||||
@ -1231,16 +1055,9 @@ Wallet.prototype._importKey = async function _importKey(acct, ring, passphrase)
|
||||
path.encrypted = true;
|
||||
}
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
await account.savePath(path);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
const b = this.db.batch();
|
||||
await account.savePath(b, path);
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1271,14 +1088,6 @@ Wallet.prototype.importAddress = async function importAddress(acct, address) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._importAddress = async function _importAddress(acct, address) {
|
||||
if (!address) {
|
||||
address = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
assert(address.network === this.network,
|
||||
'Network mismatch for address.');
|
||||
|
||||
@ -1298,16 +1107,9 @@ Wallet.prototype._importAddress = async function _importAddress(acct, address) {
|
||||
|
||||
const path = Path.fromAddress(account, address);
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
await account.savePath(path);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
const b = this.db.batch();
|
||||
await account.savePath(b, path);
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1881,29 +1683,14 @@ Wallet.prototype.setLookahead = async function setLookahead(acct, lookahead) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._setLookahead = async function _setLookahead(acct, lookahead) {
|
||||
if (lookahead == null) {
|
||||
lookahead = acct;
|
||||
acct = null;
|
||||
}
|
||||
|
||||
if (acct == null)
|
||||
acct = 0;
|
||||
|
||||
const account = await this.getAccount(acct);
|
||||
|
||||
if (!account)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
this.start();
|
||||
|
||||
try {
|
||||
await account.setLookahead(lookahead);
|
||||
} catch (e) {
|
||||
this.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.commit();
|
||||
const b = this.db.batch();
|
||||
await account.setLookahead(b, lookahead);
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1933,6 +1720,7 @@ Wallet.prototype.syncOutputDepth = async function syncOutputDepth(tx) {
|
||||
}
|
||||
|
||||
const derived = [];
|
||||
const b = this.db.batch();
|
||||
|
||||
for (const [acct, paths] of map) {
|
||||
let receive = -1;
|
||||
@ -1963,33 +1751,17 @@ Wallet.prototype.syncOutputDepth = async function syncOutputDepth(tx) {
|
||||
const account = await this.getAccount(acct);
|
||||
assert(account);
|
||||
|
||||
const ring = await account.syncDepth(receive, change, nested);
|
||||
const ring = await account.syncDepth(b, receive, change, nested);
|
||||
|
||||
if (ring)
|
||||
derived.push(ring);
|
||||
}
|
||||
|
||||
await b.write();
|
||||
|
||||
return derived;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a redeem script or witness script by hash.
|
||||
* @param {Hash} hash - Can be a ripemd160 or a sha256.
|
||||
* @returns {Script}
|
||||
*/
|
||||
|
||||
Wallet.prototype.getRedeem = async function getRedeem(hash) {
|
||||
if (typeof hash === 'string')
|
||||
hash = Buffer.from(hash, 'hex');
|
||||
|
||||
const ring = await this.getKey(hash.toString('hex'));
|
||||
|
||||
if (!ring)
|
||||
return null;
|
||||
|
||||
return ring.getRedeem(hash);
|
||||
};
|
||||
|
||||
/**
|
||||
* Build input scripts templates for a transaction (does not
|
||||
* sign, only creates signature slots). Only builds scripts
|
||||
@ -2021,7 +1793,7 @@ Wallet.prototype.sign = async function sign(mtx, passphrase) {
|
||||
|
||||
const rings = await this.deriveInputs(mtx);
|
||||
|
||||
return await mtx.signAsync(rings, Script.hashType.ALL, this.wdb.workers);
|
||||
return mtx.signAsync(rings, Script.hashType.ALL, this.wdb.workers);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2128,23 +1900,14 @@ Wallet.prototype.add = async function add(tx, block) {
|
||||
*/
|
||||
|
||||
Wallet.prototype._add = async function _add(tx, block) {
|
||||
this.txdb.start();
|
||||
const details = await this.txdb.add(tx, block);
|
||||
|
||||
let details, derived;
|
||||
try {
|
||||
details = await this.txdb._add(tx, block);
|
||||
if (details)
|
||||
derived = await this.syncOutputDepth(tx);
|
||||
} catch (e) {
|
||||
this.txdb.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
await this.txdb.commit();
|
||||
|
||||
if (derived && derived.length > 0) {
|
||||
this.wdb.emit('address', this.id, derived);
|
||||
this.emit('address', derived);
|
||||
if (details) {
|
||||
const derived = await this.syncOutputDepth(tx);
|
||||
if (derived.length > 0) {
|
||||
this.wdb.emit('address', this.id, derived);
|
||||
this.emit('address', derived);
|
||||
}
|
||||
}
|
||||
|
||||
return details;
|
||||
@ -2375,10 +2138,6 @@ Wallet.prototype.getBalance = async function getBalance(acct) {
|
||||
*/
|
||||
|
||||
Wallet.prototype.getRange = async function getRange(acct, options) {
|
||||
if (acct && typeof acct === 'object') {
|
||||
options = acct;
|
||||
acct = null;
|
||||
}
|
||||
const account = await this.ensureIndex(acct);
|
||||
return await this.txdb.getRange(account, options);
|
||||
};
|
||||
@ -2395,29 +2154,6 @@ Wallet.prototype.getLast = async function getLast(acct, limit) {
|
||||
return await this.txdb.getLast(account, limit);
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve account index.
|
||||
* @private
|
||||
* @param {(Number|String)?} acct
|
||||
* @param {Function} errback - Returns [Error].
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
Wallet.prototype.ensureIndex = async function ensureIndex(acct, enforce) {
|
||||
if (acct == null) {
|
||||
if (enforce)
|
||||
throw new Error('No account provided.');
|
||||
return null;
|
||||
}
|
||||
|
||||
const index = await this.getAccountIndex(acct);
|
||||
|
||||
if (index === -1)
|
||||
throw new Error('Account not found.');
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current receive address.
|
||||
* @param {String?} enc - `"base58"` or `null`.
|
||||
|
||||
@ -184,8 +184,10 @@ WalletDB.prototype._close = async function _close() {
|
||||
if (this.http && this.options.listen)
|
||||
await this.http.close();
|
||||
|
||||
for (const wallet of this.wallets.values())
|
||||
for (const wallet of this.wallets.values()) {
|
||||
await wallet.destroy();
|
||||
this.unregister(wallet);
|
||||
}
|
||||
|
||||
await this.db.close();
|
||||
|
||||
@ -303,14 +305,14 @@ WalletDB.prototype.disconnect = async function disconnect() {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.init = async function init() {
|
||||
const state = await this.getState();
|
||||
const cache = await this.getState();
|
||||
|
||||
if (state) {
|
||||
this.state = state;
|
||||
if (cache) {
|
||||
this.state = cache;
|
||||
return;
|
||||
}
|
||||
|
||||
const batch = this.db.batch();
|
||||
const b = this.db.batch();
|
||||
|
||||
let tip = null;
|
||||
|
||||
@ -320,27 +322,27 @@ WalletDB.prototype.init = async function init() {
|
||||
for (let height = 0; height < hashes.length; height++) {
|
||||
const hash = hashes[height];
|
||||
const meta = new BlockMeta(hash, height);
|
||||
batch.put(layout.h(height), meta.toHash());
|
||||
b.put(layout.h(height), meta.toHash());
|
||||
tip = meta;
|
||||
}
|
||||
} else {
|
||||
tip = new BlockMeta(this.network.genesis.hash, 0);
|
||||
batch.put(layout.h(0), tip.toHash());
|
||||
b.put(layout.h(0), tip.toHash());
|
||||
}
|
||||
|
||||
assert(tip);
|
||||
|
||||
const pending = this.state.clone();
|
||||
pending.startHeight = tip.height;
|
||||
pending.startHash = tip.hash;
|
||||
pending.height = tip.height;
|
||||
pending.marked = false;
|
||||
const state = this.state.clone();
|
||||
state.startHeight = tip.height;
|
||||
state.startHash = tip.hash;
|
||||
state.height = tip.height;
|
||||
state.marked = false;
|
||||
|
||||
batch.put(layout.R, pending.toRaw());
|
||||
b.put(layout.R, state.toRaw());
|
||||
|
||||
await batch.write();
|
||||
await b.write();
|
||||
|
||||
this.state = pending;
|
||||
this.state = state;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -587,7 +589,7 @@ WalletDB.prototype.wipe = async function wipe() {
|
||||
lte: Buffer.from([0xff])
|
||||
});
|
||||
|
||||
const batch = this.db.batch();
|
||||
const b = this.db.batch();
|
||||
|
||||
let total = 0;
|
||||
|
||||
@ -600,7 +602,7 @@ WalletDB.prototype.wipe = async function wipe() {
|
||||
case 0x6f: // o
|
||||
case 0x68: // h
|
||||
case 0x52: // R
|
||||
batch.del(key);
|
||||
b.del(key);
|
||||
total += 1;
|
||||
break;
|
||||
}
|
||||
@ -608,7 +610,7 @@ WalletDB.prototype.wipe = async function wipe() {
|
||||
|
||||
this.logger.warning('Wiped %d txdb records.', total);
|
||||
|
||||
await batch.write();
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -646,83 +648,6 @@ WalletDB.prototype.getDepth = async function getDepth() {
|
||||
return depth + 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Start batch.
|
||||
* @private
|
||||
* @param {WalletID} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.start = function start(wallet) {
|
||||
assert(!wallet.current, 'WDB: Batch already started.');
|
||||
wallet.current = this.db.batch();
|
||||
wallet.accountCache.start();
|
||||
wallet.pathCache.start();
|
||||
return wallet.current;
|
||||
};
|
||||
|
||||
/**
|
||||
* Drop batch.
|
||||
* @private
|
||||
* @param {WalletID} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.drop = function drop(wallet) {
|
||||
const batch = this.batch(wallet);
|
||||
wallet.current = null;
|
||||
wallet.accountCache.drop();
|
||||
wallet.pathCache.drop();
|
||||
batch.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear batch.
|
||||
* @private
|
||||
* @param {WalletID} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.clear = function clear(wallet) {
|
||||
const batch = this.batch(wallet);
|
||||
wallet.accountCache.clear();
|
||||
wallet.pathCache.clear();
|
||||
batch.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get batch.
|
||||
* @private
|
||||
* @param {WalletID} wid
|
||||
* @returns {Leveldown.Batch}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.batch = function batch(wallet) {
|
||||
assert(wallet.current, 'WDB: Batch does not exist.');
|
||||
return wallet.current;
|
||||
};
|
||||
|
||||
/**
|
||||
* Save batch.
|
||||
* @private
|
||||
* @param {WalletID} wid
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.commit = async function commit(wallet) {
|
||||
const batch = this.batch(wallet);
|
||||
|
||||
try {
|
||||
await batch.write();
|
||||
} catch (e) {
|
||||
wallet.current = null;
|
||||
wallet.accountCache.drop();
|
||||
wallet.pathCache.drop();
|
||||
throw e;
|
||||
}
|
||||
|
||||
wallet.current = null;
|
||||
wallet.accountCache.commit();
|
||||
wallet.pathCache.commit();
|
||||
};
|
||||
|
||||
/**
|
||||
* Test the bloom filter against a tx or address hash.
|
||||
* @private
|
||||
@ -793,7 +718,7 @@ WalletDB.prototype.unregister = function unregister(wallet) {
|
||||
* @returns {Promise} - Returns {WalletID}.
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getWalletID = async function getWalletID(id) {
|
||||
WalletDB.prototype.getWID = async function getWID(id) {
|
||||
if (!id)
|
||||
return null;
|
||||
|
||||
@ -817,7 +742,7 @@ WalletDB.prototype.getWalletID = async function getWalletID(id) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.get = async function get(id) {
|
||||
const wid = await this.getWalletID(id);
|
||||
const wid = await this.getWID(id);
|
||||
|
||||
if (!wid)
|
||||
return null;
|
||||
@ -863,13 +788,12 @@ WalletDB.prototype._get = async function _get(wid) {
|
||||
* @param {Wallet} wallet
|
||||
*/
|
||||
|
||||
WalletDB.prototype.save = function save(wallet) {
|
||||
WalletDB.prototype.save = function save(b, wallet) {
|
||||
const wid = wallet.wid;
|
||||
const id = wallet.id;
|
||||
const batch = this.batch(wallet);
|
||||
|
||||
batch.put(layout.w(wid), wallet.toRaw());
|
||||
batch.put(layout.l(id), U32(wid));
|
||||
b.put(layout.w(wid), wallet.toRaw());
|
||||
b.put(layout.l(id), U32(wid));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -897,27 +821,23 @@ WalletDB.prototype.rename = async function rename(wallet, id) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype._rename = async function _rename(wallet, id) {
|
||||
const old = wallet.id;
|
||||
|
||||
if (!common.isName(id))
|
||||
throw new Error('WDB: Bad wallet ID.');
|
||||
|
||||
if (await this.has(id))
|
||||
throw new Error('WDB: ID not available.');
|
||||
|
||||
const batch = this.start(wallet);
|
||||
batch.del(layout.l(old));
|
||||
const old = wallet.id;
|
||||
const b = this.db.batch();
|
||||
|
||||
b.del(layout.l(old));
|
||||
|
||||
wallet.id = id;
|
||||
wallet.txdb.id = id;
|
||||
|
||||
this.save(wallet);
|
||||
this.save(b, wallet);
|
||||
|
||||
await this.commit(wallet);
|
||||
|
||||
const paths = wallet.pathCache.values();
|
||||
|
||||
for (const path of paths)
|
||||
path.id = id;
|
||||
await b.write();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -926,16 +846,13 @@ WalletDB.prototype._rename = async function _rename(wallet, id) {
|
||||
* @param {String} name
|
||||
*/
|
||||
|
||||
WalletDB.prototype.renameAccount = function renameAccount(account, name) {
|
||||
const wallet = account.wallet;
|
||||
const batch = this.batch(wallet);
|
||||
|
||||
WalletDB.prototype.renameAccount = function renameAccount(b, account, name) {
|
||||
// Remove old wid/name->account index.
|
||||
batch.del(layout.i(account.wid, account.name));
|
||||
b.del(layout.i(account.wid, account.name));
|
||||
|
||||
account.name = name;
|
||||
|
||||
this.saveAccount(account);
|
||||
this.saveAccount(b, account);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1018,7 +935,7 @@ WalletDB.prototype._create = async function _create(options) {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.has = async function has(id) {
|
||||
const wid = await this.getWalletID(id);
|
||||
const wid = await this.getWID(id);
|
||||
return wid != null;
|
||||
};
|
||||
|
||||
@ -1106,23 +1023,19 @@ WalletDB.prototype.getAccountName = async function getAccountName(wid, index) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.saveAccount = function saveAccount(account) {
|
||||
WalletDB.prototype.saveAccount = function saveAccount(b, account) {
|
||||
const wid = account.wid;
|
||||
const wallet = account.wallet;
|
||||
const index = account.accountIndex;
|
||||
const name = account.name;
|
||||
const batch = this.batch(wallet);
|
||||
|
||||
// Account data
|
||||
batch.put(layout.a(wid, index), account.toRaw());
|
||||
b.put(layout.a(wid, index), account.toRaw());
|
||||
|
||||
// Name->Index lookups
|
||||
batch.put(layout.i(wid, name), U32(index));
|
||||
b.put(layout.i(wid, name), U32(index));
|
||||
|
||||
// Index->Name lookups
|
||||
batch.put(layout.n(wid, index), Buffer.from(name, 'ascii'));
|
||||
|
||||
wallet.accountCache.push(index, account);
|
||||
b.put(layout.n(wid, index), Buffer.from(name, 'ascii'));
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1143,8 +1056,8 @@ WalletDB.prototype.hasAccount = function hasAccount(wid, index) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.saveKey = function saveKey(wallet, ring) {
|
||||
return this.savePath(wallet, ring.toPath());
|
||||
WalletDB.prototype.saveKey = function saveKey(b, wid, ring) {
|
||||
return this.savePath(b, wid, ring.toPath());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1160,21 +1073,15 @@ WalletDB.prototype.saveKey = function saveKey(wallet, ring) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.savePath = async function savePath(wallet, path) {
|
||||
const wid = wallet.wid;
|
||||
const hash = path.hash;
|
||||
const batch = this.batch(wallet);
|
||||
|
||||
wallet.pathCache.push(hash, path);
|
||||
|
||||
WalletDB.prototype.savePath = async function savePath(b, wid, path) {
|
||||
// Address Hash -> Wallet Map
|
||||
await this.addPathMap(wallet, hash);
|
||||
await this.addPathMap(b, path.hash, wid);
|
||||
|
||||
// Wallet ID + Address Hash -> Path Data
|
||||
batch.put(layout.P(wid, hash), path.toRaw());
|
||||
b.put(layout.P(wid, path.hash), path.toRaw());
|
||||
|
||||
// Wallet ID + Account Index + Address Hash -> Dummy
|
||||
batch.put(layout.r(wid, path.account, hash), null);
|
||||
b.put(layout.r(wid, path.account, path.hash), null);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1184,13 +1091,33 @@ WalletDB.prototype.savePath = async function savePath(wallet, path) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getPath = async function getPath(wid, hash) {
|
||||
WalletDB.prototype.getPath = async function getPath(wid, id, hash) {
|
||||
const path = await this.readPath(wid, id, hash);
|
||||
|
||||
if (!path)
|
||||
return null;
|
||||
|
||||
path.name = await this.getAccountName(wid, path.account);
|
||||
assert(path.name);
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve path by hash.
|
||||
* @param {WalletID} wid
|
||||
* @param {Hash} hash
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.readPath = async function readPath(wid, id, hash) {
|
||||
const data = await this.db.get(layout.P(wid, hash));
|
||||
|
||||
if (!data)
|
||||
return null;
|
||||
|
||||
const path = Path.fromRaw(data);
|
||||
path.id = id;
|
||||
path.wid = wid;
|
||||
path.hash = hash;
|
||||
|
||||
@ -1313,28 +1240,30 @@ WalletDB.prototype.getWallets = function getWallets() {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.encryptKeys = async function encryptKeys(wallet, key) {
|
||||
const wid = wallet.wid;
|
||||
const paths = await wallet.getPaths();
|
||||
const batch = this.batch(wallet);
|
||||
WalletDB.prototype.encryptKeys = async function encryptKeys(b, wid, key) {
|
||||
const iter = this.db.iterator({
|
||||
gte: layout.P(wid, encoding.NULL_HASH),
|
||||
lte: layout.P(wid, encoding.HIGH_HASH),
|
||||
values: true
|
||||
});
|
||||
|
||||
await iter.each((k, value) => {
|
||||
const hash = layout.Pp(k);
|
||||
const path = Path.fromRaw(value);
|
||||
|
||||
for (let path of paths) {
|
||||
if (!path.data)
|
||||
continue;
|
||||
return;
|
||||
|
||||
assert(!path.encrypted);
|
||||
|
||||
const hash = Buffer.from(path.hash, 'hex');
|
||||
const iv = hash.slice(0, 16);
|
||||
const bhash = Buffer.from(hash, 'hex');
|
||||
const iv = bhash.slice(0, 16);
|
||||
|
||||
path = path.clone();
|
||||
path.data = aes.encipher(path.data, key, iv);
|
||||
path.encrypted = true;
|
||||
|
||||
wallet.pathCache.push(path.hash, path);
|
||||
|
||||
batch.put(layout.P(wid, path.hash), path.toRaw());
|
||||
}
|
||||
b.put(k, path.toRaw());
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1344,28 +1273,30 @@ WalletDB.prototype.encryptKeys = async function encryptKeys(wallet, key) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.decryptKeys = async function decryptKeys(wallet, key) {
|
||||
const wid = wallet.wid;
|
||||
const paths = await wallet.getPaths();
|
||||
const batch = this.batch(wallet);
|
||||
WalletDB.prototype.decryptKeys = async function decryptKeys(b, wid, key) {
|
||||
const iter = this.db.iterator({
|
||||
gte: layout.P(wid, encoding.NULL_HASH),
|
||||
lte: layout.P(wid, encoding.HIGH_HASH),
|
||||
values: true
|
||||
});
|
||||
|
||||
await iter.each((k, value) => {
|
||||
const hash = layout.Pp(k);
|
||||
const path = Path.fromRaw(value);
|
||||
|
||||
for (let path of paths) {
|
||||
if (!path.data)
|
||||
continue;
|
||||
return;
|
||||
|
||||
assert(path.encrypted);
|
||||
|
||||
const hash = Buffer.from(path.hash, 'hex');
|
||||
const iv = hash.slice(0, 16);
|
||||
const bhash = Buffer.from(hash, 'hex');
|
||||
const iv = bhash.slice(0, 16);
|
||||
|
||||
path = path.clone();
|
||||
path.data = aes.decipher(path.data, key, iv);
|
||||
path.encrypted = false;
|
||||
|
||||
wallet.pathCache.push(path.hash, path);
|
||||
|
||||
batch.put(layout.P(wid, path.hash), path.toRaw());
|
||||
}
|
||||
b.put(k, path.toRaw());
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1500,14 +1431,14 @@ WalletDB.prototype.getState = async function getState() {
|
||||
*/
|
||||
|
||||
WalletDB.prototype.syncState = async function syncState(tip) {
|
||||
const batch = this.db.batch();
|
||||
const b = this.db.batch();
|
||||
const state = this.state.clone();
|
||||
|
||||
if (tip.height < state.height) {
|
||||
// Hashes ahead of our new tip
|
||||
// that we need to delete.
|
||||
while (state.height !== tip.height) {
|
||||
batch.del(layout.h(state.height));
|
||||
b.del(layout.h(state.height));
|
||||
state.height -= 1;
|
||||
}
|
||||
} else if (tip.height > state.height) {
|
||||
@ -1522,10 +1453,10 @@ WalletDB.prototype.syncState = async function syncState(tip) {
|
||||
}
|
||||
|
||||
// Save tip and state.
|
||||
batch.put(layout.h(tip.height), tip.toHash());
|
||||
batch.put(layout.R, state.toRaw());
|
||||
b.put(layout.h(tip.height), tip.toHash());
|
||||
b.put(layout.R, state.toRaw());
|
||||
|
||||
await batch.write();
|
||||
await b.write();
|
||||
|
||||
this.state = state;
|
||||
};
|
||||
@ -1542,9 +1473,9 @@ WalletDB.prototype.markState = async function markState(block) {
|
||||
state.startHash = block.hash;
|
||||
state.marked = true;
|
||||
|
||||
const batch = this.db.batch();
|
||||
batch.put(layout.R, state.toRaw());
|
||||
await batch.write();
|
||||
const b = this.db.batch();
|
||||
b.put(layout.R, state.toRaw());
|
||||
await b.write();
|
||||
|
||||
this.state = state;
|
||||
};
|
||||
@ -1571,15 +1502,13 @@ WalletDB.prototype.getMap = async function getMap(key) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addMap = async function addMap(wallet, key) {
|
||||
const wid = wallet.wid;
|
||||
const batch = this.batch(wallet);
|
||||
WalletDB.prototype.addMap = async function addMap(b, key, wid) {
|
||||
const data = await this.db.get(key);
|
||||
|
||||
if (!data) {
|
||||
const map = new MapRecord();
|
||||
map.add(wid);
|
||||
batch.put(key, map.toRaw());
|
||||
b.put(key, map.toRaw());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1592,7 +1521,7 @@ WalletDB.prototype.addMap = async function addMap(wallet, key) {
|
||||
bw.copy(data, 4, data.length);
|
||||
bw.writeU32(wid);
|
||||
|
||||
batch.put(key, bw.render());
|
||||
b.put(key, bw.render());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1602,9 +1531,7 @@ WalletDB.prototype.addMap = async function addMap(wallet, key) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.removeMap = async function removeMap(wallet, key) {
|
||||
const wid = wallet.wid;
|
||||
const batch = this.batch(wallet);
|
||||
WalletDB.prototype.removeMap = async function removeMap(b, key, wid) {
|
||||
const map = await this.getMap(key);
|
||||
|
||||
if (!map)
|
||||
@ -1614,11 +1541,11 @@ WalletDB.prototype.removeMap = async function removeMap(wallet, key) {
|
||||
return;
|
||||
|
||||
if (map.size === 0) {
|
||||
batch.del(key);
|
||||
b.del(key);
|
||||
return;
|
||||
}
|
||||
|
||||
batch.put(key, map.toRaw());
|
||||
b.put(key, map.toRaw());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1638,9 +1565,9 @@ WalletDB.prototype.getPathMap = function getPathMap(hash) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addPathMap = function addPathMap(wallet, hash) {
|
||||
WalletDB.prototype.addPathMap = function addPathMap(b, hash, wid) {
|
||||
this.addHash(hash);
|
||||
return this.addMap(wallet, layout.p(hash));
|
||||
return this.addMap(b, layout.p(hash), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1650,8 +1577,8 @@ WalletDB.prototype.addPathMap = function addPathMap(wallet, hash) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.removePathMap = function removePathMap(wallet, hash) {
|
||||
return this.removeMap(wallet, layout.p(hash));
|
||||
WalletDB.prototype.removePathMap = function removePathMap(b, hash, wid) {
|
||||
return this.removeMap(b, layout.p(hash), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1671,8 +1598,8 @@ WalletDB.prototype.getBlockMap = async function getBlockMap(height) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addBlockMap = function addBlockMap(wallet, height) {
|
||||
return this.addMap(wallet, layout.b(height));
|
||||
WalletDB.prototype.addBlockMap = function addBlockMap(b, height, wid) {
|
||||
return this.addMap(b, layout.b(height), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1682,8 +1609,8 @@ WalletDB.prototype.addBlockMap = function addBlockMap(wallet, height) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.removeBlockMap = function removeBlockMap(wallet, height) {
|
||||
return this.removeMap(wallet, layout.b(height));
|
||||
WalletDB.prototype.removeBlockMap = function removeBlockMap(b, height, wid) {
|
||||
return this.removeMap(b, layout.b(height), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1703,8 +1630,8 @@ WalletDB.prototype.getTXMap = function getTXMap(hash) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addTXMap = function addTXMap(wallet, hash) {
|
||||
return this.addMap(wallet, layout.T(hash));
|
||||
WalletDB.prototype.addTXMap = function addTXMap(b, hash, wid) {
|
||||
return this.addMap(b, layout.T(hash), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1714,8 +1641,8 @@ WalletDB.prototype.addTXMap = function addTXMap(wallet, hash) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.removeTXMap = function removeTXMap(wallet, hash) {
|
||||
return this.removeMap(wallet, layout.T(hash));
|
||||
WalletDB.prototype.removeTXMap = function removeTXMap(b, hash, wid) {
|
||||
return this.removeMap(b, layout.T(hash), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1724,7 +1651,7 @@ WalletDB.prototype.removeTXMap = function removeTXMap(wallet, hash) {
|
||||
* @returns {Promise}
|
||||
*/
|
||||
|
||||
WalletDB.prototype.getOutpointMap = async function getOutpointMap(hash, index) {
|
||||
WalletDB.prototype.getOutpointMap = function getOutpointMap(hash, index) {
|
||||
return this.getMap(layout.o(hash, index));
|
||||
};
|
||||
|
||||
@ -1735,9 +1662,9 @@ WalletDB.prototype.getOutpointMap = async function getOutpointMap(hash, index) {
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.addOutpointMap = async function addOutpointMap(wallet, hash, index) {
|
||||
this.addOutpoint(hash, index);
|
||||
return this.addMap(wallet, layout.o(hash, index));
|
||||
WalletDB.prototype.addOutpointMap = async function addOutpointMap(b, hash, index, wid) {
|
||||
await this.addOutpoint(hash, index);
|
||||
return this.addMap(b, layout.o(hash, index), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1747,8 +1674,8 @@ WalletDB.prototype.addOutpointMap = async function addOutpointMap(wallet, hash,
|
||||
* @param {Number} wid
|
||||
*/
|
||||
|
||||
WalletDB.prototype.removeOutpointMap = async function removeOutpointMap(wallet, hash, index) {
|
||||
return this.removeMap(wallet, layout.o(hash, index));
|
||||
WalletDB.prototype.removeOutpointMap = function removeOutpointMap(b, hash, index, wid) {
|
||||
return this.removeMap(b, layout.o(hash, index), wid);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -118,14 +118,14 @@ async function testP2SH(witness, nesting) {
|
||||
const carol = await wdb.create(options);
|
||||
const recipient = await wdb.create();
|
||||
|
||||
await alice.addSharedKey(bob.account.accountKey);
|
||||
await alice.addSharedKey(carol.account.accountKey);
|
||||
await alice.addSharedKey(0, bob.account.accountKey);
|
||||
await alice.addSharedKey(0, carol.account.accountKey);
|
||||
|
||||
await bob.addSharedKey(alice.account.accountKey);
|
||||
await bob.addSharedKey(carol.account.accountKey);
|
||||
await bob.addSharedKey(0, alice.account.accountKey);
|
||||
await bob.addSharedKey(0, carol.account.accountKey);
|
||||
|
||||
await carol.addSharedKey(alice.account.accountKey);
|
||||
await carol.addSharedKey(bob.account.accountKey);
|
||||
await carol.addSharedKey(0, alice.account.accountKey);
|
||||
await carol.addSharedKey(0, bob.account.accountKey);
|
||||
|
||||
// Our p2sh address
|
||||
const addr1 = alice.account[receive].getAddress();
|
||||
@ -262,15 +262,8 @@ describe('Wallet', function() {
|
||||
|
||||
it('should create and get wallet', async () => {
|
||||
const wallet1 = await wdb.create();
|
||||
|
||||
await wallet1.destroy();
|
||||
|
||||
const wallet2 = await wdb.get(wallet1.id);
|
||||
|
||||
assert(wallet1 !== wallet2);
|
||||
assert(wallet1.master !== wallet2.master);
|
||||
assert(wallet1.master.key.equals(wallet2.master.key));
|
||||
assert(wallet1.account.accountKey.equals(wallet2.account.accountKey));
|
||||
assert(wallet1 === wallet2);
|
||||
});
|
||||
|
||||
it('should sign/verify p2pkh tx', async () => {
|
||||
@ -295,7 +288,7 @@ describe('Wallet', function() {
|
||||
const xpriv = HD.PrivateKey.generate();
|
||||
const key = xpriv.deriveAccount(44, 0).toPublic();
|
||||
|
||||
await wallet.addSharedKey(key);
|
||||
await wallet.addSharedKey(0, key);
|
||||
|
||||
const script = Script.fromMultisig(1, 2, [
|
||||
wallet.account.receive.getPublicKey(),
|
||||
@ -684,7 +677,7 @@ describe('Wallet', function() {
|
||||
assert.strictEqual(t2.getSize(), 521);
|
||||
assert.strictEqual(t2.getVirtualSize(), 521);
|
||||
|
||||
let balance;
|
||||
let balance = null;
|
||||
bob.once('balance', (b) => {
|
||||
balance = b;
|
||||
});
|
||||
@ -927,6 +920,7 @@ describe('Wallet', function() {
|
||||
passphrase: 'foo'
|
||||
});
|
||||
await wallet.destroy();
|
||||
wdb.unregister(wallet);
|
||||
}
|
||||
|
||||
const wallet = await wdb.get('foobar');
|
||||
@ -1156,7 +1150,7 @@ describe('Wallet', function() {
|
||||
|
||||
it('should get range of txs', async () => {
|
||||
const wallet = currentWallet;
|
||||
const txs = await wallet.getRange({
|
||||
const txs = await wallet.getRange(null, {
|
||||
start: util.now() - 1000
|
||||
});
|
||||
assert.strictEqual(txs.length, 2);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user