diff --git a/src/js/ripple/amount.js b/src/js/ripple/amount.js index 74edc964..2c4e953f 100644 --- a/src/js/ripple/amount.js +++ b/src/js/ripple/amount.js @@ -30,6 +30,12 @@ function Amount() { this._issuer = new UInt160(); } +/** + * Set strict_mode = false to disable amount range checking + */ + +Amount.strict_mode = true; + var consts = { currency_xns: 0, currency_one: 1, @@ -338,6 +344,9 @@ Amount.prototype.canonicalize = function(roundingMode) { }; Amount.prototype._check_limits = function() { + if (!Amount.strict_mode) { + return this; + } if (this._value.isNaN() || this._value.isZero()) { return this; } diff --git a/src/js/ripple/serializedtypes.js b/src/js/ripple/serializedtypes.js index f8fd73ec..c4b53ffa 100644 --- a/src/js/ripple/serializedtypes.js +++ b/src/js/ripple/serializedtypes.js @@ -8,10 +8,11 @@ var assert = require('assert'); var extend = require('extend'); +var GlobalBigNumber = require('bignumber.js'); var binformat = require('./binformat'); var utils = require('./utils'); +var Amount = require('./amount'); var sjcl = utils.sjcl; -var GlobalBigNumber = require('bignumber.js'); var UInt128 = require('./uint128').UInt128; var UInt160 = require('./uint160').UInt160; @@ -288,6 +289,7 @@ var STCurrency = new SerializedType({ var STAmount = exports.Amount = new SerializedType({ serialize: function (so, val) { var amount = Amount.from_json(val); + if (!amount.is_valid()) { throw new Error('Not a valid Amount object.'); } @@ -301,12 +303,12 @@ var STAmount = exports.Amount = new SerializedType({ if (amount.is_native()) { var valueHex = value.abs().toString(16); - if (value.abs().greaterThan(Amount.bi_xns_max)) { + if (Amount.strict_mode && value.abs().greaterThan(Amount.bi_xns_max)) { throw new Error('Value out of bounds'); } // Enforce correct length (64 bits) - if (valueHex.length > 16) { + if (Amount.strict_mode && valueHex.length > 16) { throw new Error('Value out of bounds'); } diff --git a/test/serializedobject-test.js b/test/serializedobject-test.js index 9149e05d..03616294 100644 --- a/test/serializedobject-test.js +++ b/test/serializedobject-test.js @@ -1,6 +1,7 @@ -var assert = require('assert'); +var assert = require('assert'); var SerializedObject = require('ripple-lib').SerializedObject; -var sjcl = require('ripple-lib').sjcl; +var Amount = require('ripple-lib').Amount; +var sjcl = require('ripple-lib').sjcl; // Shortcuts var hex = sjcl.codec.hex; @@ -54,6 +55,56 @@ describe('Serialized object', function() { }); }); + describe('#from_json(v).to_json() == v -- invalid amount', function(){ + it('outputs same as passed to from_json', function() { + var input_json = { + Account: 'rUR9gTCcrUY9fMkz9rwcM9urPREh3LKXoW', + Fee: '10', + Flags: 0, + Sequence: 65, + SigningPubKey: '033D0B1FB932E0408C119107483190B61561DCE8529E29CB5D1C69128DA54DA715', + TakerGets: '2188313981504612096', + TakerPays: { + currency: 'USD', + issuer: 'r9rp9MUFRJVCVLRm3MTmUvSPNBSL3BuEFx', + value: '99999999999' + }, + TransactionType: 'OfferCreate', + TxnSignature: '304602210085C6AE945643150E6D450CF796E45D74FB24B4E03E964A29CC6AFFEB346C77C80221009BE1B6678CF6C2E61F8F2696144C75AFAF66DF4FC0733DF9118EDEFEEFE33243' + }; + + assert.throws(function() { + SerializedObject.from_json(input_json).to_json(); + }); + }); + }); + + describe('#from_json(v).to_json() == v -- invalid amount, strict_mode = false', function(){ + it('outputs same as passed to from_json', function() { + var input_json = { + Account: 'rUR9gTCcrUY9fMkz9rwcM9urPREh3LKXoW', + Fee: '10', + Flags: 0, + Sequence: 65, + SigningPubKey: '033D0B1FB932E0408C119107483190B61561DCE8529E29CB5D1C69128DA54DA715', + TakerGets: '2188313981504612096', + TakerPays: { + currency: 'USD', + issuer: 'r9rp9MUFRJVCVLRm3MTmUvSPNBSL3BuEFx', + value: '99999999999' + }, + TransactionType: 'OfferCreate', + TxnSignature: 'FFFFFF210085C6AE945643150E6D450CF796E45D74FB24B4E03E964A29CC6AFFEB346C77C80221009BE1B6678CF6C2E61F8F2696144C75AFAF66DF4FC0733DF9118EDEFEEFE33243' + }; + + var strictMode = Amount.strict_mode; + Amount.strict_mode = false; + var output_json = SerializedObject.from_json(input_json).to_json(); + assert.deepEqual(input_json, output_json); + Amount.strict_mode = strictMode; + }); + }); + describe('#from_json', function() { it('understands TransactionType as a Number', function() { var input_json = {