Replace sjcl.bn with bn.js

This commit is contained in:
Nicholas Dudfield
2015-08-12 14:09:39 +07:00
parent ed971bc41c
commit b0889b4afe
12 changed files with 367 additions and 388 deletions

5
npm-shrinkwrap.json generated
View File

@@ -22,6 +22,11 @@
"version": "2.0.7", "version": "2.0.7",
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.7.tgz" "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-2.0.7.tgz"
}, },
"bn.js": {
"version": "3.1.1",
"from": "bn.js@*",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-3.1.1.tgz"
},
"es6-promisify": { "es6-promisify": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-2.0.0.tgz",

View File

@@ -18,15 +18,16 @@
"async": "~0.9.0", "async": "~0.9.0",
"babel-runtime": "^5.5.4", "babel-runtime": "^5.5.4",
"bignumber.js": "^2.0.3", "bignumber.js": "^2.0.3",
"bn.js": "^3.1.1",
"es6-promisify": "^2.0.0", "es6-promisify": "^2.0.0",
"extend": "~1.2.1", "extend": "~1.2.1",
"https-proxy-agent": "^1.0.0", "https-proxy-agent": "^1.0.0",
"is-my-json-valid": "^2.12.0", "is-my-json-valid": "^2.12.0",
"lodash": "^3.1.0", "lodash": "^3.1.0",
"lru-cache": "~2.5.0", "lru-cache": "~2.5.0",
"ripple-lib-transactionparser": "^0.5.0",
"ripple-address-codec": "^1.6.0", "ripple-address-codec": "^1.6.0",
"ripple-keypairs": "^0.7.3", "ripple-keypairs": "^0.7.3",
"ripple-lib-transactionparser": "^0.5.0",
"ripple-wallet-generator": "^1.0.3", "ripple-wallet-generator": "^1.0.3",
"sjcl-extended": "ripple/sjcl-extended#1.0.3", "sjcl-extended": "ripple/sjcl-extended#1.0.3",
"ws": "~0.7.1" "ws": "~0.7.1"

View File

@@ -2,12 +2,13 @@
'use strict'; 'use strict';
var fs = require('fs'); var fs = require('fs');
var Amount = require('../dist/npm').Amount; var ripple = require('../dist/npm')._DEPRECATED;
var Ledger = require('../dist/npm').Ledger; var Amount = ripple.Amount;
var Ledger = ripple.Ledger;
function parse_options(from, flags) { function parse_options(from, flags) {
var argv = from.slice(), var argv = from.slice();
opts_ = {argv: argv}; var opts_ = {argv: argv};
flags.forEach(function(f) { flags.forEach(function(f) {
// Do we have the flag? // Do we have the flag?

View File

@@ -1,6 +1,6 @@
'use strict'; 'use strict';
const sjcl = require('./utils').sjcl; const BN = require('bn.js');
const extend = require('extend'); const extend = require('extend');
const {encode, decode} = require('ripple-address-codec'); const {encode, decode} = require('ripple-address-codec');
@@ -44,11 +44,11 @@ Base.encode_check = function(version, input, alphabet) {
}; };
// --> input : String // --> input : String
// <-- NaN || sjcl.bn // <-- NaN || BN
Base.decode_check = function(version, input, alphabet) { Base.decode_check = function(version, input, alphabet) {
try { try {
const decoded = decode(input, {version, alphabet}); const decoded = decode(input, {version, alphabet});
return sjcl.bn.fromBits(sjcl.codec.bytes.toBits(decoded)); return new BN(decoded);
} catch (e) { } catch (e) {
return NaN; return NaN;
} }

View File

@@ -1,19 +1,18 @@
/* eslint-disable valid-jsdoc */
'use strict'; 'use strict';
var Transaction = require('./transaction').Transaction; const Transaction = require('./transaction').Transaction;
var SHAMap = require('./shamap').SHAMap; const SHAMap = require('./shamap').SHAMap;
var SHAMapTreeNode = require('./shamap').SHAMapTreeNode; const SHAMapTreeNode = require('./shamap').SHAMapTreeNode;
var SerializedObject = require('./serializedobject').SerializedObject; const SerializedObject = require('./serializedobject').SerializedObject;
var stypes = require('./serializedtypes'); const stypes = require('./serializedtypes');
var UInt160 = require('./uint160').UInt160; const UInt160 = require('./uint160').UInt160;
var Currency = require('./currency').Currency; const Currency = require('./currency').Currency;
function Ledger() { function Ledger() {
this.ledger_json = {}; this.ledger_json = {};
} }
Ledger.from_json = function(v) { Ledger.from_json = function(v) {
var ledger = new Ledger(); const ledger = new Ledger();
ledger.parse_json(v); ledger.parse_json(v);
return ledger; return ledger;
}; };
@@ -23,14 +22,13 @@ Ledger.space = require('./ledgerspaces');
/** /**
* Generate the key for an AccountRoot entry. * Generate the key for an AccountRoot entry.
* *
* @param {String|UInt160} account Ripple Account * @param {String|UInt160} accountArg - Ripple Account
* @return {UInt256} * @return {UInt256}
*/ */
Ledger.calcAccountRootEntryHash = Ledger.calcAccountRootEntryHash =
Ledger.prototype.calcAccountRootEntryHash = function(account) { Ledger.prototype.calcAccountRootEntryHash = function(accountArg) {
account = UInt160.from_json(account); const account = UInt160.from_json(accountArg);
const index = new SerializedObject();
var index = new SerializedObject();
index.append([0, Ledger.space.account.charCodeAt(0)]); index.append([0, Ledger.space.account.charCodeAt(0)]);
index.append(account.to_bytes()); index.append(account.to_bytes());
@@ -41,17 +39,15 @@ Ledger.prototype.calcAccountRootEntryHash = function(account) {
/** /**
* Generate the key for an Offer entry. * Generate the key for an Offer entry.
* *
* @param {String|UInt160} account Ripple Account * @param {String|UInt160} accountArg - Ripple Account
* @param {Number} sequence Sequence number of the OfferCreate transaction * @param {Number} sequence - Sequence number of the OfferCreate transaction
* that instantiated this offer. * that instantiated this offer.
* @return {UInt256} * @return {UInt256}
*/ */
Ledger.calcOfferEntryHash = Ledger.calcOfferEntryHash =
Ledger.prototype.calcOfferEntryHash = function(account, sequence) { Ledger.prototype.calcOfferEntryHash = function(accountArg, sequence) {
account = UInt160.from_json(account); const account = UInt160.from_json(accountArg);
sequence = parseInt(sequence, 10); const index = new SerializedObject();
var index = new SerializedObject();
index.append([0, Ledger.space.offer.charCodeAt(0)]); index.append([0, Ledger.space.offer.charCodeAt(0)]);
index.append(account.to_bytes()); index.append(account.to_bytes());
@@ -65,17 +61,17 @@ Ledger.prototype.calcOfferEntryHash = function(account, sequence) {
* *
* The ordering of the two account parameters does not matter. * The ordering of the two account parameters does not matter.
* *
* @param {String|UInt160} account1 First Ripple Account * @param {String|UInt160} _account1 - First Ripple Account
* @param {String|UInt160} account2 Second Ripple Account * @param {String|UInt160} _account2 - Second Ripple Account
* @param {String|Currency} currency The currency code * @param {String|Currency} _currency - The currency code
* @return {UInt256} * @return {UInt256}
*/ */
Ledger.calcRippleStateEntryHash = Ledger.calcRippleStateEntryHash =
Ledger.prototype.calcRippleStateEntryHash = function( Ledger.prototype.calcRippleStateEntryHash = function(
account1, account2, currency) { _account1, _account2, _currency) {
currency = Currency.from_json(currency); const currency = Currency.from_json(_currency);
account1 = UInt160.from_json(account1); const account1 = UInt160.from_json(_account1);
account2 = UInt160.from_json(account2); const account2 = UInt160.from_json(_account2);
if (!account1.is_valid()) { if (!account1.is_valid()) {
throw new Error('Invalid first account'); throw new Error('Invalid first account');
@@ -87,18 +83,14 @@ Ledger.prototype.calcRippleStateEntryHash = function(
throw new Error('Invalid currency'); throw new Error('Invalid currency');
} }
// The lower ID has to come first const swap = account1.greater_than(account2);
if (account1.to_bn().greaterEquals(account2.to_bn())) { const lowAccount = swap ? account2 : account1;
var tmp = account2; const highAccount = swap ? account1 : account2;
account2 = account1; const index = new SerializedObject();
account1 = tmp;
}
var index = new SerializedObject();
index.append([0, Ledger.space.rippleState.charCodeAt(0)]); index.append([0, Ledger.space.rippleState.charCodeAt(0)]);
index.append(account1.to_bytes()); index.append(lowAccount.to_bytes());
index.append(account2.to_bytes()); index.append(highAccount.to_bytes());
index.append(currency.to_bytes()); index.append(currency.to_bytes());
return index.hash(); return index.hash();
@@ -109,13 +101,13 @@ Ledger.prototype.parse_json = function(v) {
}; };
Ledger.prototype.calc_tx_hash = function() { Ledger.prototype.calc_tx_hash = function() {
var tx_map = new SHAMap(); const tx_map = new SHAMap();
this.ledger_json.transactions.forEach(function(tx_json) { this.ledger_json.transactions.forEach(function(tx_json) {
var tx = Transaction.from_json(tx_json); const tx = Transaction.from_json(tx_json);
var meta = SerializedObject.from_json(tx_json.metaData); const meta = SerializedObject.from_json(tx_json.metaData);
var data = new SerializedObject(); const data = new SerializedObject();
stypes.VariableLength.serialize(data, tx.serialize().to_hex()); stypes.VariableLength.serialize(data, tx.serialize().to_hex());
stypes.VariableLength.serialize(data, meta.to_hex()); stypes.VariableLength.serialize(data, meta.to_hex());
tx_map.add_item(tx.hash(), data, SHAMapTreeNode.TYPE_TRANSACTION_MD); tx_map.add_item(tx.hash(), data, SHAMapTreeNode.TYPE_TRANSACTION_MD);
@@ -125,22 +117,23 @@ Ledger.prototype.calc_tx_hash = function() {
}; };
/** /**
* @param options .sanity_test {Boolean} * @param {Object} options - object
* @return hash of shamap
* *
* If `true`, will serialize each accountState item to binary and then back to * @param {Boolean} [options.sanity_test=false] - If `true`, will serialize each
* json before finally serializing for hashing. This is mostly to expose any * accountState item to binary and then back to json before finally
* issues with ripple-lib's binary <--> json codecs. * serializing for hashing. This is mostly to expose any issues with
* ripple-lib's binary <--> json codecs.
* *
* @return {UInt256} - hash of shamap
*/ */
Ledger.prototype.calc_account_hash = function(options) { Ledger.prototype.calc_account_hash = function(options) {
var account_map = new SHAMap(); const account_map = new SHAMap();
var erred; let erred;
this.ledger_json.accountState.forEach(function(le) { this.ledger_json.accountState.forEach(function(le) {
var data = SerializedObject.from_json(le); let data = SerializedObject.from_json(le);
var json; let json;
if (options && options.sanity_test) { if (options && options.sanity_test) {
try { try {
json = data.to_json(); json = data.to_json();

View File

@@ -7,6 +7,7 @@
const {KeyPair, KeyType} = require('ripple-keypairs'); const {KeyPair, KeyType} = require('ripple-keypairs');
const codec = require('ripple-address-codec'); const codec = require('ripple-address-codec');
const extend = require('extend'); const extend = require('extend');
const BN = require('bn.js');
const utils = require('./utils'); const utils = require('./utils');
const sjcl = utils.sjcl; const sjcl = utils.sjcl;
@@ -54,7 +55,7 @@ Seed.prototype.parse_base58 = function(j) {
} else { } else {
try { try {
const {bytes, type} = codec.decodeSeed(j); const {bytes, type} = codec.decodeSeed(j);
this._value = sjcl.bn.fromBits(sjcl.codec.bytes.toBits(bytes)); this._value = new BN(bytes);
this._type = type; this._type = type;
} catch (e) { } catch (e) {
this._value = NaN; this._value = NaN;

View File

@@ -1,8 +1,8 @@
'use strict'; 'use strict';
const _ = require('lodash');
const assert = require('assert'); const assert = require('assert');
const extend = require('extend'); const extend = require('extend');
const BN = require('bn.js');
const binformat = require('./binformat'); const binformat = require('./binformat');
const stypes = require('./serializedtypes'); const stypes = require('./serializedtypes');
const utils = require('./utils'); const utils = require('./utils');
@@ -28,13 +28,9 @@ Object.keys(binformat.ter).forEach(function(key) {
TRANSACTION_RESULTS[binformat.ter[key]] = key; TRANSACTION_RESULTS[binformat.ter[key]] = key;
}); });
function normalize_sjcl_bn_hex(string) { function fieldType(fieldName) {
const hex = string.slice(2); // remove '0x' prefix const fieldDef = binformat.fieldsInverseMap[fieldName];
// now strip leading zeros return binformat.types[fieldDef[0]];
const i = _.findIndex(hex, function(c) {
return c !== '0';
});
return i >= 0 ? hex.slice(i) : '0';
} }
function SerializedObject(buf) { function SerializedObject(buf) {
@@ -231,12 +227,12 @@ SerializedObject.prototype.to_json = function() {
return output; return output;
}; };
SerializedObject.jsonify_structure = function(structure, field_name) { SerializedObject.jsonify_structure = function(structure, fieldName) {
let output; let output;
switch (typeof structure) { switch (typeof structure) {
case 'number': case 'number':
switch (field_name) { switch (fieldName) {
case 'LedgerEntryType': case 'LedgerEntryType':
output = LEDGER_ENTRY_TYPES[structure]; output = LEDGER_ENTRY_TYPES[structure];
break; break;
@@ -257,11 +253,10 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
if (typeof structure.to_json === 'function') { if (typeof structure.to_json === 'function') {
output = structure.to_json(); output = structure.to_json();
} else if (structure instanceof sjcl.bn) { } else if (structure instanceof BN) {
output = ('0000000000000000' + // We assume that any BN is a UInt64 field
normalize_sjcl_bn_hex(structure.toString()) assert.equal(fieldType(fieldName), 'Int64');
.toUpperCase() output = utils.arrayToHex(structure.toArray('bn', 8));
).slice(-16);
} else { } else {
// new Array or Object // new Array or Object
output = new structure.constructor(); output = new structure.constructor();

View File

@@ -10,13 +10,13 @@
const assert = require('assert'); const assert = require('assert');
const extend = require('extend'); const extend = require('extend');
const BN = require('bn.js');
const GlobalBigNumber = require('bignumber.js'); const GlobalBigNumber = require('bignumber.js');
const Amount = require('./amount').Amount; const Amount = require('./amount').Amount;
const Currency = require('./currency').Currency; const Currency = require('./currency').Currency;
const binformat = require('./binformat'); const binformat = require('./binformat');
const utils = require('./utils'); const utils = require('./utils');
const sjcl = utils.sjcl; const sjcl = utils.sjcl;
const SJCL_BN = sjcl.bn;
const UInt128 = require('./uint128').UInt128; const UInt128 = require('./uint128').UInt128;
const UInt160 = require('./uint160').UInt160; const UInt160 = require('./uint160').UInt160;
@@ -44,8 +44,7 @@ function isHexInt64String(val) {
return isString(val) && /^[0-9A-F]{0,16}$/i.test(val); return isString(val) && /^[0-9A-F]{0,16}$/i.test(val);
} }
function serializeBits(so, bits, noLength) { function serializeBytes(so, byteData, noLength) {
const byteData = sjcl.codec.bytes.fromBits(bits);
if (!noLength) { if (!noLength) {
SerializedType.serialize_varint(so, byteData.length); SerializedType.serialize_varint(so, byteData.length);
} }
@@ -53,18 +52,7 @@ function serializeBits(so, bits, noLength) {
} }
function serializeHex(so, hexData, noLength) { function serializeHex(so, hexData, noLength) {
serializeBits(so, sjcl.codec.hex.toBits(hexData), noLength); serializeBytes(so, utils.hexToArray(hexData), noLength);
}
/**
* parses bytes as hex
*
* @param {Array} byte_array bytes
* @return {String} hex string
*/
function convertByteArrayToHex(byte_array) {
return sjcl.codec.hex.fromBits(sjcl.codec.bytes.toBits(byte_array))
.toUpperCase();
} }
function convertHexToString(hexString) { function convertHexToString(hexString) {
@@ -308,25 +296,27 @@ const STInt64 = exports.Int64 = new SerializedType({
if (value < 0) { if (value < 0) {
throw new Error('Negative value for unsigned Int64 is invalid.'); throw new Error('Negative value for unsigned Int64 is invalid.');
} }
bigNumObject = new SJCL_BN(value, 10); bigNumObject = new BN(value, 10);
} else if (isString(value)) { } else if (isString(value)) {
if (!isHexInt64String(value)) { if (!isHexInt64String(value)) {
throw new Error('Not a valid hex Int64.'); throw new Error('Not a valid hex Int64.');
} }
bigNumObject = new SJCL_BN(value, 16); bigNumObject = new BN(value, 16);
} else if (value instanceof SJCL_BN) { } else if (value instanceof BN) {
if (!value.greaterEquals(0)) { if (value.cmpn(0) < 0) {
throw new Error('Negative value for unsigned Int64 is invalid.'); throw new Error('Negative value for unsigned Int64 is invalid.');
} }
bigNumObject = value; bigNumObject = value;
} else { } else {
throw new Error('Invalid type for Int64'); throw new Error('Invalid type for Int64: ' + (typeof value) + ' value');
} }
serializeBits(so, bigNumObject.toBits(64), true); // noLength = true // `'be'` means big endian, and the following arg is the byte length, which
// it will pad with 0s to if not enough bytes, or throw if over
serializeBytes(so, bigNumObject.toArray('be', 8), /* noLength= */true);
}, },
parse: function(so) { parse: function(so) {
const bytes = so.read(8); const bytes = so.read(8);
return SJCL_BN.fromBits(sjcl.codec.bytes.toBits(bytes)); return new BN(bytes);
} }
}); });
@@ -338,7 +328,7 @@ const STHash128 = exports.Hash128 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash128'); throw new Error('Invalid Hash128');
} }
serializeBits(so, hash.to_bits(), true); // noLength = true serializeBytes(so, hash.to_bytes(), true); // noLength = true
}, },
parse: function(so) { parse: function(so) {
return UInt128.from_bytes(so.read(16)); return UInt128.from_bytes(so.read(16));
@@ -353,7 +343,7 @@ const STHash256 = exports.Hash256 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash256'); throw new Error('Invalid Hash256');
} }
serializeBits(so, hash.to_bits(), true); // noLength = true serializeBytes(so, hash.to_bytes(), true); // noLength = true
}, },
parse: function(so) { parse: function(so) {
return UInt256.from_bytes(so.read(32)); return UInt256.from_bytes(so.read(32));
@@ -368,7 +358,7 @@ const STHash160 = exports.Hash160 = new SerializedType({
if (!hash.is_valid()) { if (!hash.is_valid()) {
throw new Error('Invalid Hash160'); throw new Error('Invalid Hash160');
} }
serializeBits(so, hash.to_bits(), true); // noLength = true serializeBytes(so, hash.to_bytes(), true); // noLength = true
}, },
parse: function(so) { parse: function(so) {
return UInt160.from_bytes(so.read(20)); return UInt160.from_bytes(so.read(20));
@@ -582,7 +572,7 @@ const STVL = exports.VariableLength = exports.VL = new SerializedType({
}, },
parse: function(so) { parse: function(so) {
const len = this.parse_varint(so); const len = this.parse_varint(so);
return convertByteArrayToHex(so.read(len)); return utils.arrayToHex(so.read(len));
} }
}); });
@@ -594,7 +584,7 @@ const STAccount = exports.Account = new SerializedType({
if (!account.is_valid()) { if (!account.is_valid()) {
throw new Error('Invalid account!'); throw new Error('Invalid account!');
} }
serializeBits(so, account.to_bits()); serializeBytes(so, account.to_bytes());
}, },
parse: function(so) { parse: function(so) {
const len = this.parse_varint(so); const len = this.parse_varint(so);
@@ -807,27 +797,27 @@ exports.STMemo = new SerializedType({
if (parsedType !== 'unformatted_memo') { if (parsedType !== 'unformatted_memo') {
output.parsed_memo_type = parsedType; output.parsed_memo_type = parsedType;
} }
/*eslint-disable no-empty*/ /* eslint-disable no-empty */
} catch (e) { } catch (e) {
// empty // empty
// we don't know what's in the binary, apparently it's not a UTF-8 // we don't know what's in the binary, apparently it's not a UTF-8
// string // string
// this is fine, we won't add the parsed_memo_type field // this is fine, we won't add the parsed_memo_type field
} }
/*eslint-enable no-empty*/ /* eslint-enable no-empty */
} }
if (output.MemoFormat !== undefined) { if (output.MemoFormat !== undefined) {
try { try {
output.parsed_memo_format = convertHexToString(output.MemoFormat); output.parsed_memo_format = convertHexToString(output.MemoFormat);
/*eslint-disable no-empty*/ /* eslint-disable no-empty */
} catch (e) { } catch (e) {
// empty // empty
// we don't know what's in the binary, apparently it's not a UTF-8 // we don't know what's in the binary, apparently it's not a UTF-8
// string // string
// this is fine, we won't add the parsed_memo_format field // this is fine, we won't add the parsed_memo_format field
} }
/*eslint-enable no-empty*/ /* eslint-enable no-empty */
} }
if (output.MemoData !== undefined) { if (output.MemoData !== undefined) {
@@ -842,7 +832,7 @@ exports.STMemo = new SerializedType({
// otherwise see if we can parse text // otherwise see if we can parse text
output.parsed_memo_data = convertHexToString(output.MemoData); output.parsed_memo_data = convertHexToString(output.MemoData);
} }
/*eslint-disable no-empty*/ /* eslint-disable no-empty */
} catch(e) { } catch(e) {
// empty // empty
// we'll fail in case the content does not match what the MemoFormat // we'll fail in case the content does not match what the MemoFormat
@@ -850,7 +840,7 @@ exports.STMemo = new SerializedType({
// this is fine, we won't add the parsed_memo_data, the user has to // this is fine, we won't add the parsed_memo_data, the user has to
// parse themselves // parse themselves
} }
/*eslint-enable no-empty*/ /* eslint-enable no-empty */
} }
so.read(1); so.read(1);

View File

@@ -1,10 +1,12 @@
'use strict'; 'use strict';
/*eslint new-cap: 1*/ /* eslint new-cap: 1 */
const assert = require('assert'); const assert = require('assert');
const lodash = require('lodash'); const lodash = require('lodash');
const utils = require('./utils'); const utils = require('./utils');
const BN = require('bn.js');
const sjcl = utils.sjcl; const sjcl = utils.sjcl;
// //
@@ -14,7 +16,7 @@ const sjcl = utils.sjcl;
// //
function UInt() { function UInt() {
// Internal form: NaN or sjcl.bn // Internal form: NaN or BN
this._value = NaN; this._value = NaN;
} }
@@ -108,16 +110,33 @@ UInt.prototype.copyTo = function(d) {
return d; return d;
}; };
UInt.prototype.equals = function(d) { UInt.prototype.equals = function(o) {
return this.is_valid() && d.is_valid() && this._value.equals(d._value); return this.is_valid() &&
o.is_valid() &&
// This throws but the expression will short circuit
this.cmp(o) === 0;
};
UInt.prototype.cmp = function(o) {
assert(this.is_valid() && o.is_valid());
return this._value.cmp(o._value);
};
UInt.prototype.greater_than = function(o) {
return this.cmp(o) > 0;
};
UInt.prototype.less_than = function(o) {
return this.cmp(o) < 0;
}; };
UInt.prototype.is_valid = function() { UInt.prototype.is_valid = function() {
return this._value instanceof sjcl.bn; return this._value instanceof BN;
}; };
UInt.prototype.is_zero = function() { UInt.prototype.is_zero = function() {
return this.is_valid() && this._value.equals(new sjcl.bn(0)); // cmpn means cmp with N)umber
return this.is_valid() && this._value.cmpn(0) === 0;
}; };
/** /**
@@ -150,14 +169,14 @@ UInt.prototype.parse_generic = function(j) {
case subclass.STR_ZERO: case subclass.STR_ZERO:
case subclass.ACCOUNT_ZERO: case subclass.ACCOUNT_ZERO:
case subclass.HEX_ZERO: case subclass.HEX_ZERO:
this._value = new sjcl.bn(0); this._value = new BN(0);
break; break;
case '1': case '1':
case subclass.STR_ONE: case subclass.STR_ONE:
case subclass.ACCOUNT_ONE: case subclass.ACCOUNT_ONE:
case subclass.HEX_ONE: case subclass.HEX_ONE:
this._value = new sjcl.bn(1); this._value = new BN(1);
break; break;
default: default:
@@ -165,7 +184,7 @@ UInt.prototype.parse_generic = function(j) {
switch (j.length) { switch (j.length) {
case subclass.width: case subclass.width:
const hex = utils.arrayToHex(utils.stringToArray(j)); const hex = utils.arrayToHex(utils.stringToArray(j));
this._value = new sjcl.bn(hex, 16); this._value = new BN(hex, 16);
break; break;
case subclass.width * 2: case subclass.width * 2:
// Assume hex, check char set // Assume hex, check char set
@@ -187,7 +206,7 @@ UInt.prototype.parse_generic = function(j) {
UInt.prototype.parse_hex = function(j) { UInt.prototype.parse_hex = function(j) {
if (new RegExp(`^[0-9A-Fa-f]{${this.constructor.width * 2}}$`).test(j)) { if (new RegExp(`^[0-9A-Fa-f]{${this.constructor.width * 2}}$`).test(j)) {
this._value = new sjcl.bn(j, 16); this._value = new BN(j, 16);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -199,9 +218,8 @@ UInt.prototype.parse_hex = function(j) {
UInt.prototype.parse_bits = function(j) { UInt.prototype.parse_bits = function(j) {
if (sjcl.bitArray.bitLength(j) === this.constructor.width * 8) { if (sjcl.bitArray.bitLength(j) === this.constructor.width * 8) {
this._value = sjcl.bn.fromBits(j); const bytes = sjcl.codec.bytes.fromBits(j);
// let bytes = sjcl.codec.bytes.fromBits(j); this.parse_bytes(bytes);
// this.parse_bytes(bytes);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -211,11 +229,9 @@ UInt.prototype.parse_bits = function(j) {
return this; return this;
}; };
UInt.prototype.parse_bytes = function(j) { UInt.prototype.parse_bytes = function(j) {
if (Array.isArray(j) && j.length === this.constructor.width) { if (Array.isArray(j) && j.length === this.constructor.width) {
const bits = sjcl.codec.bytes.toBits(j); this._value = new BN(j);
this._value = sjcl.bn.fromBits(bits);
} else { } else {
this._value = NaN; this._value = NaN;
} }
@@ -225,26 +241,13 @@ UInt.prototype.parse_bytes = function(j) {
return this; return this;
}; };
UInt.prototype.parse_json = UInt.prototype.parse_hex; UInt.prototype.parse_json = UInt.prototype.parse_hex;
UInt.prototype.parse_bn = function(j) {
if ((j instanceof sjcl.bn) && j.bitLength() <= this.constructor.width * 8) {
this._value = new sjcl.bn(j);
} else {
this._value = NaN;
}
this._update();
return this;
};
UInt.prototype.parse_number = function(j) { UInt.prototype.parse_number = function(j) {
this._value = NaN; this._value = NaN;
if (typeof j === 'number' && isFinite(j) && j >= 0) { if (typeof j === 'number' && isFinite(j) && j >= 0) {
this._value = new sjcl.bn(j); this._value = new BN(j);
} }
this._update(); this._update();
@@ -258,7 +261,7 @@ UInt.prototype.to_bytes = function() {
return null; return null;
} }
return sjcl.codec.bytes.fromBits(this.to_bits()); return this._value.toArray('be', this.constructor.width);
}; };
UInt.prototype.to_hex = function() { UInt.prototype.to_hex = function() {
@@ -266,27 +269,18 @@ UInt.prototype.to_hex = function() {
return null; return null;
} }
return sjcl.codec.hex.fromBits(this.to_bits()).toUpperCase(); return utils.arrayToHex(this.to_bytes());
}; };
UInt.prototype.to_json = UInt.prototype.to_hex; UInt.prototype.to_json = UInt.prototype.to_hex;
// Convert from internal form.
UInt.prototype.to_bits = function() { UInt.prototype.to_bits = function() {
if (!this.is_valid()) { if (!this.is_valid()) {
return null; return null;
} }
return this._value.toBits(this.constructor.width * 8); return sjcl.codec.bytes.toBits(this.to_bytes());
};
UInt.prototype.to_bn = function() {
if (!this.is_valid()) {
return null;
}
const bits = this.to_bits();
return sjcl.bn.fromBits(bits);
}; };
exports.UInt = UInt; exports.UInt = UInt;

View File

@@ -77,7 +77,7 @@ function hexToArray(h) {
function arrayToHex(a) { function arrayToHex(a) {
return a.map(function(byteValue) { return a.map(function(byteValue) {
const hex = byteValue.toString(16); const hex = byteValue.toString(16).toUpperCase();
return hex.length > 1 ? hex : '0' + hex; return hex.length > 1 ? hex : '0' + hex;
}).join(''); }).join('');
} }

View File

@@ -31,11 +31,11 @@ describe('Base', function() {
describe('decode_check', function() { describe('decode_check', function() {
it('rrrrrrrrrrrrrrrrrrrrrhoLvTp', function() { it('rrrrrrrrrrrrrrrrrrrrrhoLvTp', function() {
const decoded = Base.decode_check(0, 'rrrrrrrrrrrrrrrrrrrrrhoLvTp'); const decoded = Base.decode_check(0, 'rrrrrrrrrrrrrrrrrrrrrhoLvTp');
assert(decoded.equals(0)); assert(decoded.cmpn(0) === 0);
}); });
it('rrrrrrrrrrrrrrrrrrrrBZbvji', function() { it('rrrrrrrrrrrrrrrrrrrrBZbvji', function() {
const decoded = Base.decode_check(0, 'rrrrrrrrrrrrrrrrrrrrBZbvji'); const decoded = Base.decode_check(0, 'rrrrrrrrrrrrrrrrrrrrBZbvji');
assert(decoded.equals(1)); assert(decoded.cmpn(1) === 0);
}); });
}); });
describe('decode-encode identity', function() { describe('decode-encode identity', function() {

File diff suppressed because it is too large Load Diff