bech32: refactor.

This commit is contained in:
Christopher Jeffrey 2017-05-13 15:13:42 -07:00
parent 83060ee964
commit a9ea4e5531
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 83 additions and 28 deletions

View File

@ -9,16 +9,18 @@ var i, end, addr;
var addrs = []; var addrs = [];
end = bench('serialize'); end = bench('serialize');
for (i = 0; i < 10000; i++) { for (i = 0; i < 100000; i++) {
addr = Address.fromProgram(0, crypto.randomBytes(20)); addr = Address.fromProgram(0, crypto.randomBytes(20));
addrs.push(addr.toBech32()); addrs.push(addr.toBech32());
} }
end(i); end(i);
end = bench('parse'); end = bench('parse');
for (i = 0; i < 10000; i++) { for (i = 0; i < 100000; i++) {
addr = addrs[i]; addr = addrs[i];
addr = Address.fromBech32(addr); addr = Address.fromBech32(addr);
addrs[i] = addr; addrs[i] = addr;
} }
end(i); end(i);
console.error(addrs);

View File

@ -236,9 +236,7 @@ Address.prototype.toBech32 = function toBech32(network) {
network = Network.get(network); network = Network.get(network);
hrp = network.addressPrefix.bech32; hrp = network.addressPrefix.bech32;
data = bech32.bitsify(hash, 65, 8, 5, version, 0); return bech32.encode(hrp, version, hash);
return bech32.encode(hrp, data);
}; };
/** /**
@ -389,23 +387,18 @@ Address.fromBase58 = function fromBase58(address, network) {
/** /**
* Inject properties from bech32 address. * Inject properties from bech32 address.
* @private * @private
* @param {String} data * @param {String} str
* @param {Network?} network * @param {Network?} network
* @throws Parse error * @throws Parse error
*/ */
Address.prototype.fromBech32 = function fromBech32(data, network) { Address.prototype.fromBech32 = function fromBech32(str, network) {
var type = Address.types.WITNESS; var type = Address.types.WITNESS;
var i, addr, hash, version; var i, addr;
assert(typeof data === 'string'); assert(typeof str === 'string');
addr = bech32.decode(data); addr = bech32.decode(str);
if (addr.data.length < 1)
throw new Error('Invalid bech32 data length.');
version = addr.data[0];
if (network) { if (network) {
network = Network.get(network); network = Network.get(network);
@ -421,9 +414,7 @@ Address.prototype.fromBech32 = function fromBech32(data, network) {
assert(i < networks.types.length, 'Unknown bech32 address prefix.'); assert(i < networks.types.length, 'Unknown bech32 address prefix.');
} }
hash = bech32.bitsify(addr.data, 84, 5, 8, -1, 1); return this.fromHash(addr.hash, type, addr.version, network.type);
return this.fromHash(hash, type, version, network.type);
}; };
/** /**

View File

@ -29,6 +29,8 @@
'use strict'; 'use strict';
var native = require('./native').binding;
/** /**
* @module utils/bech32 * @module utils/bech32
*/ */
@ -70,7 +72,7 @@ function polymod(pre) {
* @returns {String} * @returns {String}
*/ */
function encode(hrp, data) { function serialize(hrp, data) {
var str = ''; var str = '';
var chk = 1; var chk = 1;
var i, ch; var i, ch;
@ -124,7 +126,7 @@ function encode(hrp, data) {
* @returns {Bech32Result} * @returns {Bech32Result}
*/ */
function decode(str) { function deserialize(str) {
var chk = 1; var chk = 1;
var lower = false; var lower = false;
var upper = false; var upper = false;
@ -211,7 +213,7 @@ function decode(str) {
* @returns {Buffer} * @returns {Buffer}
*/ */
function bitsify(data, size, frombits, tobits, pad, off) { function convert(data, size, frombits, tobits, pad, off) {
var acc = 0; var acc = 0;
var bits = 0; var bits = 0;
var maxv = (1 << tobits) - 1; var maxv = (1 << tobits) - 1;
@ -248,6 +250,46 @@ function bitsify(data, size, frombits, tobits, pad, off) {
return output.slice(0, j); return output.slice(0, j);
} }
/**
* Serialize data to bech32 address.
* @param {String} hrp
* @param {Number} version
* @param {Buffer} hash
* @returns {String}
*/
function encode(hrp, version, hash) {
var data = convert(hash, 65, 8, 5, version, 0);
return serialize(hrp, data);
}
if (native && native.toBech32)
encode = native.toBech32;
/**
* Deserialize data from bech32 address.
* @param {String} str
* @returns {Object}
*/
function decode(str) {
var result = deserialize(str);
var hrp = result.hrp;
var data = result.data;
var version, hash;
if (data.length < 1)
throw new Error('Invalid bech32 data length.');
version = data[0];
hash = convert(data, 84, 5, 8, -1, 1);
return new AddrResult(hrp, version, hash);
}
if (native && native.fromBech32)
decode = native.fromBech32;
/** /**
* Bech32Result * Bech32Result
* @constructor * @constructor
@ -263,10 +305,30 @@ function Bech32Result(hrp, data) {
this.data = data; this.data = data;
} }
/**
* AddrResult
* @constructor
* @private
* @param {String} hrp
* @param {Number} version
* @param {Buffer} hash
* @property {String} hrp
* @property {Number} version
* @property {Buffer} hash
*/
function AddrResult(hrp, version, hash) {
this.hrp = hrp;
this.version = version;
this.hash = hash;
}
/* /*
* Expose * Expose
*/ */
exports.decode = decode; exports.deserialize = deserialize;
exports.serialize = serialize;
exports.convert = convert;
exports.encode = encode; exports.encode = encode;
exports.bitsify = bitsify; exports.decode = decode;

View File

@ -99,13 +99,13 @@ describe('Bech32', function() {
]; ];
function fromAddress(hrp, addr) { function fromAddress(hrp, addr) {
var dec = bech32.decode(addr); var dec = bech32.deserialize(addr);
var data; var data;
if (dec.hrp !== hrp || dec.data.length < 1 || dec.data[0] > 16) if (dec.hrp !== hrp || dec.data.length < 1 || dec.data[0] > 16)
throw new Error('Invalid bech32 prefix or data length.'); throw new Error('Invalid bech32 prefix or data length.');
data = bech32.bitsify(dec.data, 84, 5, 8, -1, 1); data = bech32.convert(dec.data, 84, 5, 8, -1, 1);
if (data.length < 2 || data.length > 40) if (data.length < 2 || data.length > 40)
throw new Error('Invalid witness program size.'); throw new Error('Invalid witness program size.');
@ -120,8 +120,8 @@ describe('Bech32', function() {
} }
function toAddress(hrp, version, program) { function toAddress(hrp, version, program) {
var data = bech32.bitsify(program, 65, 8, 5, version, 0); var data = bech32.convert(program, 65, 8, 5, version, 0);
var ret = bech32.encode(hrp, data); var ret = bech32.serialize(hrp, data);
fromAddress(hrp, ret); fromAddress(hrp, ret);
@ -135,7 +135,7 @@ describe('Bech32', function() {
VALID_CHECKSUM.forEach(function(test) { VALID_CHECKSUM.forEach(function(test) {
it('should have valid checksum for ' + test, function() { it('should have valid checksum for ' + test, function() {
var ret = bech32.decode(test); var ret = bech32.deserialize(test);
assert(ret); assert(ret);
}); });
}); });