walletdb: allow utf8 wallet and account names.

This commit is contained in:
Christopher Jeffrey 2016-08-16 20:14:58 -07:00
parent 72188e42c2
commit ebcfe66638
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 34 additions and 31 deletions

View File

@ -132,12 +132,12 @@ KeyRing.prototype.fromOptions = function fromOptions(options) {
} }
if (options.id) { if (options.id) {
assert(utils.isAlpha(options.id)); assert(utils.isName(options.id));
this.id = options.id; this.id = options.id;
} }
if (options.name) { if (options.name) {
assert(utils.isAlpha(options.name)); assert(utils.isName(options.name));
this.name = options.name; this.name = options.name;
} }
@ -782,8 +782,8 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
assert(utils.isNumber(json.n)); assert(utils.isNumber(json.n));
assert(typeof json.witness === 'boolean'); assert(typeof json.witness === 'boolean');
assert(!json.wid || utils.isNumber(json.wid)); assert(!json.wid || utils.isNumber(json.wid));
assert(!json.id || utils.isAlpha(json.id)); assert(!json.id || utils.isName(json.id));
assert(!json.name || utils.isAlpha(json.name)); assert(!json.name || utils.isName(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

@ -56,7 +56,7 @@ RBT.prototype.search = function search(key) {
var cmp; var cmp;
if (typeof key === 'string') if (typeof key === 'string')
key = new Buffer(key, 'ascii'); key = new Buffer(key, 'utf8');
while (!current.isNull()) { while (!current.isNull()) {
cmp = this.compare(key, current.key); cmp = this.compare(key, current.key);
@ -83,7 +83,7 @@ RBT.prototype.insert = function insert(key, value) {
var parent, cmp, node; var parent, cmp, node;
if (typeof key === 'string') if (typeof key === 'string')
key = new Buffer(key, 'ascii'); key = new Buffer(key, 'utf8');
if (typeof value === 'string') if (typeof value === 'string')
value = new Buffer(value, 'utf8'); value = new Buffer(value, 'utf8');
@ -186,7 +186,7 @@ RBT.prototype.remove = function remove(key) {
var cmp; var cmp;
if (typeof key === 'string') if (typeof key === 'string')
key = new Buffer(key, 'ascii'); key = new Buffer(key, 'utf8');
while (!current.isNull()) { while (!current.isNull()) {
cmp = this.compare(key, current.key); cmp = this.compare(key, current.key);
@ -526,10 +526,10 @@ RBT.prototype.range = function range(gte, lte) {
var cmp; var cmp;
if (typeof gte === 'string') if (typeof gte === 'string')
gte = new Buffer(gte, 'ascii'); gte = new Buffer(gte, 'utf8');
if (typeof lte === 'string') if (typeof lte === 'string')
lte = new Buffer(lte, 'ascii'); lte = new Buffer(lte, 'utf8');
if (gte) { if (gte) {
// Find the node closest to our gte key. // Find the node closest to our gte key.
@ -1078,7 +1078,7 @@ Iterator.prototype.seek = function seek(key) {
assert(!this.ended, 'Already ended.'); assert(!this.ended, 'Already ended.');
if (typeof key === 'string') if (typeof key === 'string')
key = new Buffer(key, 'ascii'); key = new Buffer(key, 'utf8');
this.index = utils.binarySearch(this.snapshot, key, function(a, b) { this.index = utils.binarySearch(this.snapshot, key, function(a, b) {
return self.tree.compare(a.key, b); return self.tree.compare(a.key, b);
@ -1122,7 +1122,7 @@ SENTINEL = new RBTSentinel();
function stringify(value) { function stringify(value) {
if (Buffer.isBuffer(value)) if (Buffer.isBuffer(value))
return value.toString('ascii'); return value.toString('utf8');
return value; return value;
} }

View File

@ -2401,18 +2401,18 @@ utils.mkdir = function mkdir(path, dirname) {
utils._paths = {}; utils._paths = {};
/** /**
* Test whether a string is alphanumeric * Test whether a string is eligible
* enough to use as a leveldb key. * to be used as a name or ID.
* @param {String} key * @param {String} key
* @returns {Boolean} * @returns {Boolean}
*/ */
utils.isAlpha = function isAlpha(key) { utils.isName = function isName(key) {
if (typeof key !== 'string') if (typeof key !== 'string')
return false; return false;
return key.length >= 1
&& key.length <= 40 // Maximum worst case size: 80 bytes
&& /^[\u0020-\u007e]+$/.test(key); return key.length >= 1 && key.length <= 40;
}; };
/** /**

View File

@ -114,7 +114,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
} }
if (options.id) { if (options.id) {
assert(utils.isAlpha(options.id), 'Wallet ID must be alphanumeric.'); assert(utils.isName(options.id), 'Bad wallet ID.');
id = options.id; id = options.id;
} }
@ -1933,7 +1933,7 @@ Wallet.prototype.toJSON = function toJSON() {
Wallet.prototype.fromJSON = function fromJSON(json) { Wallet.prototype.fromJSON = function fromJSON(json) {
assert(utils.isNumber(json.wid)); assert(utils.isNumber(json.wid));
assert(typeof json.initialized === 'boolean'); assert(typeof json.initialized === 'boolean');
assert(utils.isAlpha(json.id), 'Wallet ID must be alphanumeric.'); assert(utils.isName(json.id), 'Bad wallet ID.');
assert(utils.isNumber(json.accountDepth)); assert(utils.isNumber(json.accountDepth));
assert(typeof json.token === 'string'); assert(typeof json.token === 'string');
assert(json.token.length === 64); assert(json.token.length === 64);
@ -2095,7 +2095,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
assert(options, 'Options are required.'); assert(options, 'Options are required.');
assert(utils.isNumber(options.wid)); assert(utils.isNumber(options.wid));
assert(utils.isAlpha(options.id), 'Wallet ID must be alphanumeric.'); assert(utils.isName(options.id), 'Bad Wallet ID.');
assert(bcoin.hd.isHD(options.accountKey), 'Account key is required.'); 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.');
@ -2103,7 +2103,7 @@ Account.prototype.fromOptions = function fromOptions(options) {
this.id = options.id; this.id = options.id;
if (options.name != null) { if (options.name != null) {
assert(utils.isAlpha(options.name), 'Account name must be alphanumeric.'); assert(utils.isName(options.name), 'Bad account name.');
this.name = options.name; this.name = options.name;
} }
@ -2659,8 +2659,8 @@ Account.prototype.fromJSON = function fromJSON(json) {
assert.equal(json.network, this.network.type); assert.equal(json.network, this.network.type);
assert(utils.isNumber(json.wid)); assert(utils.isNumber(json.wid));
assert(utils.isAlpha(json.id), 'Account name must be alphanumeric.'); assert(utils.isName(json.id), 'Bad wallet ID.');
assert(utils.isAlpha(json.name), 'Account name must be alphanumeric.'); assert(utils.isName(json.name), 'Bad account name.');
assert(typeof json.initialized === 'boolean'); assert(typeof json.initialized === 'boolean');
assert(typeof json.type === 'string'); assert(typeof json.type === 'string');
assert(utils.isNumber(json.m)); assert(utils.isNumber(json.m));

View File

@ -15,6 +15,7 @@ var constants = bcoin.protocol.constants;
var BufferReader = require('./reader'); var BufferReader = require('./reader');
var BufferWriter = require('./writer'); var BufferWriter = require('./writer');
var TXDB = require('./txdb'); var TXDB = require('./txdb');
var MAX_POINT = String.fromCharCode(0xdbff, 0xdfff); // U+10FFFF
/* /*
* Database Layout: * Database Layout:
@ -88,13 +89,14 @@ var layout = {
return key.readUInt32BE(1, true); return key.readUInt32BE(1, true);
}, },
l: function(id) { l: function(id) {
var key = new Buffer(1 + id.length); var len = Buffer.byteLength(id, 'utf8');
var key = new Buffer(1 + len);
key[0] = 0x6c; key[0] = 0x6c;
key.write(id, 1, 'ascii'); key.write(id, 1, 'utf8');
return key; return key;
}, },
ll: function(key) { ll: function(key) {
return key.toString('ascii', 1); return key.toString('utf8', 1);
}, },
a: function a(wid, index) { a: function a(wid, index) {
var key = new Buffer(9); var key = new Buffer(9);
@ -104,14 +106,15 @@ var layout = {
return key; return key;
}, },
i: function i(wid, name) { i: function i(wid, name) {
var key = new Buffer(5 + name.length); var len = Buffer.byteLength(name, 'utf8');
var key = new Buffer(5 + len);
key[0] = 0x69; key[0] = 0x69;
key.writeUInt32BE(wid, 1, true); key.writeUInt32BE(wid, 1, true);
key.write(name, 5, 'ascii'); key.write(name, 5, 'utf8');
return key; return key;
}, },
ii: function ii(key) { ii: function ii(key) {
return [key.readUInt32BE(1, true), key.toString('ascii', 5)]; return [key.readUInt32BE(1, true), key.toString('utf8', 5)];
}, },
R: new Buffer([0x52]), R: new Buffer([0x52]),
b: function b(hash) { b: function b(hash) {
@ -759,7 +762,7 @@ WalletDB.prototype.getAccounts = function getAccounts(wid, callback) {
this.db.iterate({ this.db.iterate({
gte: layout.i(wid, ''), gte: layout.i(wid, ''),
lte: layout.i(wid, '\xff'), lte: layout.i(wid, MAX_POINT),
values: true, values: true,
parse: function(value, key) { parse: function(value, key) {
var name = layout.ii(key)[1]; var name = layout.ii(key)[1];
@ -1041,7 +1044,7 @@ WalletDB.prototype.getAddresses = function getAddresses(wid, callback) {
WalletDB.prototype.getWallets = function getWallets(callback) { WalletDB.prototype.getWallets = function getWallets(callback) {
this.db.iterate({ this.db.iterate({
gte: layout.l(''), gte: layout.l(''),
lte: layout.l('\xff'), lte: layout.l(MAX_POINT),
transform: function(key) { transform: function(key) {
return layout.ll(key); return layout.ll(key);
} }