more type checking.

This commit is contained in:
Christopher Jeffrey 2016-07-05 16:08:05 -07:00
parent bbe8943bf4
commit f8fadb73a7
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 141 additions and 41 deletions

View File

@ -73,49 +73,73 @@ function KeyRing(options) {
KeyRing.prototype.fromOptions = function fromOptions(options) { KeyRing.prototype.fromOptions = function fromOptions(options) {
var i; var i;
assert(options.key);
if (options.network) if (options.network)
this.network = bcoin.network.get(options.network); this.network = bcoin.network.get(options.network);
if (options.type) if (options.type) {
assert(options.type === 'pubkeyhash' || options.type === 'multisig');
this.type = options.type; this.type = options.type;
}
if (options.m) if (options.m != null) {
assert(utils.isNumber(options.m));
this.m = options.m; this.m = options.m;
}
if (options.n) if (options.n != null) {
assert(utils.isNumber(options.n));
this.n = options.n; this.n = options.n;
}
if (options.witness != null) if (options.witness != null) {
assert(typeof options.witness === 'boolean');
this.witness = options.witness; this.witness = options.witness;
}
if (options.id) if (options.id) {
assert(utils.isAlpha(options.id));
this.id = options.id; this.id = options.id;
}
if (options.name) if (options.name) {
assert(utils.isAlpha(options.name));
this.name = options.name; this.name = options.name;
}
if (options.account != null) if (options.account != null) {
assert(utils.isNumber(options.account));
this.account = options.account; this.account = options.account;
}
if (options.change != null) if (options.change != null) {
assert(utils.isNumber(options.change));
this.change = options.change; this.change = options.change;
}
if (options.index != null) if (options.index != null) {
assert(utils.isNumber(options.index));
this.index = options.index; this.index = options.index;
}
this.key = options.key; this.key = options.key;
if (this.key.getPublicKey)
this.key = this.key.getPublicKey();
assert(Buffer.isBuffer(this.key));
if (this.n > 1) if (this.n > 1)
this.type = 'multisig'; this.type = 'multisig';
assert(this.type === 'pubkeyhash' || this.type === 'multisig');
if (this.m < 1 || this.m > this.n) if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n'); throw new Error('m ranges between 1 and n');
this.addKey(this.key); this.addKey(this.key);
if (options.keys) { if (options.keys) {
assert(Array.isArray(options.keys));
for (i = 0; i < options.keys.length; i++) for (i = 0; i < options.keys.length; i++)
this.addKey(options.keys[i]); this.addKey(options.keys[i]);
} }
@ -139,6 +163,8 @@ KeyRing.fromOptions = function fromOptions(options) {
*/ */
KeyRing.prototype.addKey = function addKey(key) { KeyRing.prototype.addKey = function addKey(key) {
assert(Buffer.isBuffer(key));
if (utils.indexOf(this.keys, key) !== -1) if (utils.indexOf(this.keys, key) !== -1)
return; return;
@ -154,6 +180,8 @@ KeyRing.prototype.addKey = function addKey(key) {
*/ */
KeyRing.prototype.removeKey = function removeKey(key) { KeyRing.prototype.removeKey = function removeKey(key) {
assert(Buffer.isBuffer(key));
if (this.keys.length === this.n) if (this.keys.length === this.n)
throw new Error('Cannot remove key.'); throw new Error('Cannot remove key.');
@ -639,12 +667,12 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
assert(json); assert(json);
assert(typeof json.network === 'string'); assert(typeof json.network === 'string');
assert(typeof json.type === 'string'); assert(json.type === 'pubkeyhash' || json.type === 'multisig');
assert(utils.isNumber(json.m)); assert(utils.isNumber(json.m));
assert(utils.isNumber(json.n)); assert(utils.isNumber(json.n));
assert(typeof json.witness === 'boolean'); assert(typeof json.witness === 'boolean');
assert(!json.id || typeof json.id === 'string'); assert(!json.id || utils.isAlpha(json.id));
assert(!json.name || typeof json.name === 'string'); assert(!json.name || utils.isAlpha(json.name));
assert(utils.isNumber(json.account)); assert(utils.isNumber(json.account));
assert(utils.isNumber(json.change)); assert(utils.isNumber(json.change));
assert(utils.isNumber(json.index)); assert(utils.isNumber(json.index));

View File

@ -2621,3 +2621,17 @@ utils.mkdir = function mkdir(path, dirname) {
*/ */
utils._paths = {}; utils._paths = {};
/**
* Test whether a string is alphanumeric
* enough to use as a leveldb key.
* @param {String} key
* @returns {Boolean}
*/
utils.isAlpha = function isAlpha(key) {
if (typeof key !== 'string')
return false;
// We allow /-~ (exclusive), 0-} (inclusive)
return /^[\u0030-\u007d]+$/.test(key);
};

View File

@ -83,9 +83,24 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
master = MasterKey.fromKey(master); master = MasterKey.fromKey(master);
this.master = master; this.master = master;
this.initialized = options.initialized || false;
this.accountDepth = options.accountDepth || 0; if (options.initialized != null) {
this.id = options.id || this.getID(); assert(typeof options.initialized === 'boolean');
this.initialized = options.initialized;
}
if (options.accountDepth != null) {
assert(utils.isNumber(options.accountDepth));
this.accountDepth = options.accountDepth;
}
if (options.id) {
assert(utils.isAlpha(options.id), 'Wallet ID must be alphanumeric.');
this.id = options.id;
}
if (!this.id)
this.id = this.getID();
return this; return this;
}; };
@ -1452,11 +1467,16 @@ Wallet.prototype.toJSON = function toJSON() {
*/ */
Wallet.prototype.fromJSON = function fromJSON(json) { Wallet.prototype.fromJSON = function fromJSON(json) {
assert(utils.isAlpha(json.id), 'Wallet ID must be alphanumeric.');
assert(typeof json.initialized === 'boolean');
assert(utils.isNumber(json.accountDepth));
this.network = bcoin.network.get(json.network); this.network = bcoin.network.get(json.network);
this.id = json.id; this.id = json.id;
this.initialized = json.initialized; this.initialized = json.initialized;
this.accountDepth = json.accountDepth; this.accountDepth = json.accountDepth;
this.master = MasterKey.fromJSON(json.master); this.master = MasterKey.fromJSON(json.master);
return this; return this;
}; };
@ -1599,45 +1619,59 @@ Account.prototype.fromOptions = function fromOptions(options) {
var i; var i;
assert(options, 'Options are required.'); assert(options, 'Options are required.');
assert(options.id, 'Wallet ID is required.'); assert(utils.isAlpha(options.id), 'Wallet ID must be alphanumeric.');
assert(options.accountKey, 'Account key is required.'); assert(utils.isAlpha(options.name), 'Account name must be alphanumeric.');
assert(bcoin.hd.isHD(options.accountKey), 'Account key is required.');
assert(utils.isNumber(options.accountIndex), 'Account index is required.'); assert(utils.isNumber(options.accountIndex), 'Account index is required.');
this.id = options.id; this.id = options.id;
this.name = options.name; this.name = options.name;
if (options.witness != null) if (options.witness != null) {
assert(typeof options.witness === 'boolean');
this.witness = options.witness; this.witness = options.witness;
}
this.accountKey = options.accountKey; this.accountKey = options.accountKey;
if (options.accountIndex != null) if (options.accountIndex != null) {
assert(utils.isNumber(options.accountIndex));
this.accountIndex = options.accountIndex; this.accountIndex = options.accountIndex;
}
if (options.receiveDepth != null) if (options.receiveDepth != null) {
assert(utils.isNumber(options.receiveDepth));
this.receiveDepth = options.receiveDepth; this.receiveDepth = options.receiveDepth;
}
if (options.changeDepth != null) if (options.changeDepth != null) {
assert(utils.isNumber(options.changeDepth));
this.changeDepth = options.changeDepth; this.changeDepth = options.changeDepth;
}
if (options.type) if (options.type) {
assert(options.type === 'pubkeyhash' || options.type === 'multisig');
this.type = options.type; this.type = options.type;
}
if (options.m) if (options.m != null) {
assert(utils.isNumber(options.m));
this.m = options.m; this.m = options.m;
}
if (options.n) if (options.n != null) {
assert(utils.isNumber(options.n));
this.n = options.n; this.n = options.n;
}
if (options.initialized != null) if (options.initialized != null) {
assert(typeof options.initialized === 'boolean');
this.initialized = options.initialized; this.initialized = options.initialized;
}
if (this.n > 1) if (this.n > 1)
this.type = 'multisig'; this.type = 'multisig';
assert(this.type === 'pubkeyhash' || this.type === 'multisig',
'`type` must be multisig or pubkeyhash.');
if (this.m < 1 || this.m > this.n) if (this.m < 1 || this.m > this.n)
throw new Error('m ranges between 1 and n'); throw new Error('m ranges between 1 and n');
@ -1647,6 +1681,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
this.pushKey(this.accountKey); this.pushKey(this.accountKey);
if (options.keys) { if (options.keys) {
assert(Array.isArray(options.keys));
for (i = 0; i < options.keys.length; i++) for (i = 0; i < options.keys.length; i++)
this.pushKey(options.keys[i]); this.pushKey(options.keys[i]);
} }
@ -2258,6 +2293,17 @@ Account.prototype.fromJSON = function fromJSON(json) {
var i; var i;
assert.equal(json.network, this.network.type); assert.equal(json.network, this.network.type);
assert(utils.isAlpha(json.id), 'Wallet ID must be alphanumeric.');
assert(utils.isAlpha(json.name), 'Account name must be alphanumeric.');
assert(typeof json.initialized === 'boolean');
assert(json.type === 'pubkeyhash' || json.type === 'multisig');
assert(utils.isNumber(json.m));
assert(utils.isNumber(json.n));
assert(typeof json.witness === 'boolean');
assert(utils.isNumber(json.accountIndex));
assert(utils.isNumber(json.receiveDepth));
assert(utils.isNumber(json.changeDepth));
assert(Array.isArray(json.keys));
this.id = json.id; this.id = json.id;
this.name = json.name; this.name = json.name;
@ -2405,10 +2451,27 @@ function MasterKey(options) {
*/ */
MasterKey.prototype.fromOptions = function fromOptions(options) { MasterKey.prototype.fromOptions = function fromOptions(options) {
this.encrypted = !!options.encrypted; assert(options);
this.iv = options.iv;
this.ciphertext = options.ciphertext; if (options.encrypted != null) {
this.key = options.key || null; assert(typeof options.encrypted === 'boolean');
this.encrypted = options.encrypted;
}
if (options.iv) {
assert(Buffer.isBuffer(options.iv));
this.iv = options.iv;
}
if (options.ciphertext) {
assert(Buffer.isBuffer(options.ciphertext));
this.ciphertext = options.ciphertext;
}
if (options.key) {
assert(Buffer.isBuffer(options.key));
this.key = options.key;
}
assert(this.encrypted ? !this.key : this.key); assert(this.encrypted ? !this.key : this.key);

View File

@ -468,7 +468,7 @@ WalletDB.prototype.get = function get(id, callback) {
*/ */
WalletDB.prototype.save = function save(wallet, callback) { WalletDB.prototype.save = function save(wallet, callback) {
if (!isAlpha(wallet.id)) if (!utils.isAlpha(wallet.id))
return callback(new Error('Wallet IDs must be alphanumeric.')); return callback(new Error('Wallet IDs must be alphanumeric.'));
this.db.put('w/' + wallet.id, wallet.toRaw(), callback); this.db.put('w/' + wallet.id, wallet.toRaw(), callback);
@ -664,7 +664,7 @@ WalletDB.prototype.getAccountIndex = function getAccountIndex(id, name, callback
WalletDB.prototype.saveAccount = function saveAccount(account, callback) { WalletDB.prototype.saveAccount = function saveAccount(account, callback) {
var index, batch; var index, batch;
if (!isAlpha(account.name)) if (!utils.isAlpha(account.name))
return callback(new Error('Account names must be alphanumeric.')); return callback(new Error('Account names must be alphanumeric.'));
batch = this.db.batch(); batch = this.db.batch();
@ -1464,11 +1464,6 @@ function serializePaths(out) {
return p.render(); return p.render();
} }
function isAlpha(key) {
// We allow /-~ (exclusive), 0-} (inclusive)
return /^[\u0030-\u007d]+$/.test(key);
}
function ReadLock(parent) { function ReadLock(parent) {
if (!(this instanceof ReadLock)) if (!(this instanceof ReadLock))
return new ReadLock(parent); return new ReadLock(parent);