Compare commits

...

26 Commits

Author SHA1 Message Date
Geert Weening
ef51490a1a Bump version to 0.12.3 2015-04-13 16:27:52 -07:00
Geert Weening
c40d643238 Bump version to 0.12.3-rc2 2015-04-10 14:36:47 -07:00
Geert Weening
6f23c88567 Update release notes 2015-04-10 14:36:15 -07:00
Geert Weening
56958a6242 Merge pull request #324 from clark800/develop
Add Amount.scale
2015-04-10 13:25:57 -07:00
Chris Clark
74dac97b36 Add Amount.scale 2015-04-10 12:56:50 -07:00
Geert Weening
2f2e41c781 Bump version to 0.12.3-rc1 2015-04-08 13:36:23 -07:00
Geert Weening
8c872f71c6 Update release notes 2015-04-08 13:36:01 -07:00
wltsmrz
b40b496866 Merge pull request #322 from clark800/rest1.7
Add getLedgerSequence method
2015-04-08 11:20:46 -07:00
Geert Weening
569fec296e Merge pull request #321 from clark800/paranoia
[FIX] Fail if PRNG has not been seeded with at least 256 bits of entr…
2015-04-08 11:16:47 -07:00
Chris Clark
56d8aa797a Fix lint errors in transaction-test.js and transaction-manager-test.js 2015-04-07 18:08:07 -07:00
Chris Clark
fe7e30b737 [FIX] Fail if PRNG has not been seeded with at least 256 bits of entropy before generating ECDSA signatures 2015-04-07 18:08:02 -07:00
Chris Clark
a114281c60 Update comment about the fee base reference constant 2015-04-07 14:34:26 -07:00
Chris Clark
d09548d04d Add getLedgerSequence 2015-04-07 14:34:22 -07:00
Geert Weening
a02b8e3e5c Merge branch 'release' into develop 2015-04-06 13:00:36 -07:00
Geert Weening
2c3f9ca202 bump version to 0.12.2 2015-04-06 12:57:47 -07:00
Geert Weening
587782820d Merge pull request #318 from sublimator/serial-offender
Fix SerializedObject.append performance issue
2015-04-06 12:54:48 -07:00
Nicholas Dudfield
8fad048569 Update verify_ledger_json.js script:
* Set `Amount.strict_mode = false` in verify_ledger_json.js script
* Don't try and calculate hash of non present accountState
* Fix lint issues
2015-04-04 14:51:35 +07:00
Nicholas Dudfield
f7c35b118e Fix SerializedObject.append perf issue:
* Replace array.concat(array2) with Array.prototype.push.apply
2015-04-04 14:51:12 +07:00
Geert Weening
65a669bbb2 Merge pull request #319 from sublimator/lints
eslint fixes
2015-04-04 00:35:57 -07:00
Nicholas Dudfield
9985acc539 Fix linting issues:
* Fix lint violations in various files
* Use per-file comment directives to make new-cap a warning instead of error
  * sjcl.* don't conform to our standards and eslint exemptions are unweildy
2015-04-04 14:23:41 +07:00
Geert Weening
f1f0a43f21 Bump version to 0.12.1-rc1 2015-03-27 16:56:27 -07:00
Geert Weening
6b856c3cc5 Update release notes 2015-03-27 16:55:44 -07:00
Geert Weening
d92888ed73 Merge pull request #317 from ripple/fix-browser-log
Check that Error.stack is available, fixes logging in browser
2015-03-27 16:52:18 -07:00
wltsmrz
0357840654 Lint 2015-03-27 15:54:26 -07:00
wltsmrz
53cae3a66d Check that stack trace is available, fixes logging in browser 2015-03-27 15:49:13 -07:00
Geert Weening
949a1ca4ae Bump version to 0.12.1 2015-03-26 15:12:14 -07:00
19 changed files with 614 additions and 487 deletions

View File

@@ -1,3 +1,19 @@
##0.12.3
+ [Add getLedgerSequence to Remote](https://github.com/ripple/ripple-lib/commit/d09548d04d3238fca653d482ec1d5faa7254559a)
+ [Improve randomness when generating ECDSA signatures](https://github.com/ripple/ripple-lib/commit/fe7e30b737ead6e71adfa466f5835ba546feab31)
+ [Improve SerializedObject.append performance](https://github.com/ripple/ripple-lib/commit/f7c35b118ebba549a64bcaa1a0629385ec6dbf6f)
+ [Add `Amount.scale`. Multiply an amounts value by a scale factor](https://github.com/ripple/ripple-lib/commit/74dac97b368493056474468520f05671f458a69f)
##0.12.2
+ [Check that stack trace is available, fixes logging in browser](https://github.com/ripple/ripple-lib/commit/53cae3a66d48e88e8a6bbb96d6489ce7b9e22975)
##0.12.1
**Breaking Changes**

2
npm-shrinkwrap.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "0.12.1-rc6",
"version": "0.12.3",
"dependencies": {
"async": {
"version": "0.9.0",

View File

@@ -1,6 +1,6 @@
{
"name": "ripple-lib",
"version": "0.12.1-rc6",
"version": "0.12.3",
"description": "A JavaScript API for interacting with Ripple in Node.js and the browser",
"files": [
"src/js/*",
@@ -27,7 +27,7 @@
"devDependencies": {
"assert-diff": "^1.0.1",
"coveralls": "~2.10.0",
"eslint": "^0.13.0",
"eslint": "^0.18.0",
"gulp": "~3.8.10",
"gulp-bump": "~0.1.13",
"gulp-clean-dest": "^0.1.0",

View File

@@ -1,31 +1,34 @@
'use strict';
var fs = require('fs');
var Amount = require('../src/js/ripple').Amount;
var Ledger = require('../src/js/ripple/ledger').Ledger;
function parse_options(from, flags) {
var argv = from.slice(),
opts = {argv:argv};
opts_ = {argv: argv};
flags.forEach(function(f) {
// Do we have the flag?
var flag_index = argv.indexOf('--' + f);
// normalize the name of the flag
f = f.replace('-', '_');
// opts has Boolean value for normalized flag key
opts[f] = !!~flag_index;
if (opts[f]) {
// opts_ has Boolean value for normalized flag key
opts_[f] = flag_index !== -1;
if (opts_[f]) {
// remove the flag from the argv
argv.splice(flag_index, 1);
}
});
return opts;
return opts_;
}
var opts = parse_options(process.argv.slice(2), // remove `node` and `this.js`
['sanity-test']);
if (opts.argv.length < 1) {
console.error("Usage: scripts/verify_ledger_json path/to/ledger.json");
console.error(" optional: --sanity-test (json>binary>json>binary)");
console.error('Usage: scripts/verify_ledger_json path/to/ledger.json');
console.error(' optional: --sanity-test (json>binary>json>binary)');
process.exit(1);
}
@@ -36,14 +39,27 @@ var ledger = Ledger.from_json(JSON.parse(json));
// before finally serializing for hashing. This is mostly to expose any issues
// with ripple-libs binary <--> json codecs.
if (opts.sanity_test) {
console.log("All accountState nodes will be processed from " +
"json->binary->json->binary. This may take some time " +
"with large ledgers.");
console.log('All accountState nodes will be processed from ' +
'json->binary->json->binary. This may take some time ' +
'with large ledgers.');
}
console.log("Transaction hash in header: " + ledger.ledger_json.transaction_hash);
console.log("Calculated transaction hash: " + ledger.calc_tx_hash().to_hex());
console.log("Account state hash in header: " + ledger.ledger_json.account_hash);
console.log("Calculated account state hash: " + ledger.calc_account_hash(
{sanity_test:opts.sanity_test})
.to_hex());
// To recompute the hashes of some ledgers, we must allow values that slipped in
// before strong policies were in place.
Amount.strict_mode = false;
console.log('Transaction hash in header: ' +
ledger.ledger_json.transaction_hash);
console.log('Calculated transaction hash: ' +
ledger.calc_tx_hash().to_hex());
console.log('Account state hash in header: ' +
ledger.ledger_json.account_hash);
if (ledger.ledger_json.accountState) {
console.log('Calculated account state hash: ' +
ledger.calc_account_hash({sanity_test: opts.sanity_test})
.to_hex());
} else {
console.log('Ledger has no accountState');
}

View File

@@ -1,4 +1,4 @@
'use strict';
'use strict';
// Represent Ripple amounts and currencies.
// - Numbers in hex are big-endian.
@@ -156,6 +156,10 @@ Amount.prototype.multiply = function(multiplicand) {
return this._copy(this._value.times(multiplyBy));
};
Amount.prototype.scale = function(scaleFactor) {
return this._copy(this._value.times(scaleFactor));
};
Amount.prototype.divide = function(divisor) {
var divisorAmount = Amount.from_json(divisor);
if (!this.is_valid()) {

View File

@@ -1,14 +1,18 @@
var sjcl = require('./utils').sjcl;
'use strict';
/*eslint new-cap: 1*/
var sjcl = require('./utils').sjcl;
var UInt160 = require('./uint160').UInt160;
var UInt256 = require('./uint256').UInt256;
var Base = require('./base').Base;
var Base = require('./base').Base;
function KeyPair() {
this._curve = sjcl.ecc.curves.k256;
this._curve = sjcl.ecc.curves.k256;
this._secret = null;
this._pubkey = null;
};
}
KeyPair.from_bn_secret = function(j) {
return (j instanceof this) ? j.clone() : (new this()).parse_bn_secret(j);
@@ -20,15 +24,16 @@ KeyPair.prototype.parse_bn_secret = function(j) {
};
/**
* Returns public key as sjcl public key.
*
* @private
*
* @return {sjcl.ecc.ecdsa.publicKey} public key
*/
KeyPair.prototype._pub = function() {
var curve = this._curve;
if (!this._pubkey && this._secret) {
var exponent = this._secret._exponent;
this._pubkey = new sjcl.ecc.ecdsa.publicKey(curve, curve.G.mult(exponent));
}
@@ -36,9 +41,9 @@ KeyPair.prototype._pub = function() {
};
/**
* Returns public key in compressed format as bit array.
*
* @private
*
* @return {sjcl.bitArray} public key bits in compressed form
*/
KeyPair.prototype._pub_bits = function() {
var pub = this._pub();
@@ -56,9 +61,7 @@ KeyPair.prototype._pub_bits = function() {
};
/**
* Returns public key as hex.
*
* Key will be returned as a compressed pubkey - 33 bytes converted to hex.
* @return {String} public key bytes in compressed form, hex encoded.
*/
KeyPair.prototype.to_hex_pub = function() {
var bits = this._pub_bits();
@@ -70,7 +73,7 @@ KeyPair.prototype.to_hex_pub = function() {
return sjcl.codec.hex.fromBits(bits).toUpperCase();
};
function SHA256_RIPEMD160(bits) {
function sha256_ripemd160(bits) {
return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
}
@@ -81,7 +84,7 @@ KeyPair.prototype.get_address = function() {
return null;
}
var hash = SHA256_RIPEMD160(bits);
var hash = sha256_ripemd160(bits);
var address = UInt160.from_bits(hash);
address.set_version(Base.VER_ACCOUNT_ID);
@@ -89,8 +92,9 @@ KeyPair.prototype.get_address = function() {
};
KeyPair.prototype.sign = function(hash) {
var PARANOIA_256_BITS = 6; // sjcl constant for ensuring 256 bits of entropy
hash = UInt256.from_json(hash);
var sig = this._secret.sign(hash.to_bits(), 0);
var sig = this._secret.sign(hash.to_bits(), PARANOIA_256_BITS);
sig = this._secret.canonicalizeSignature(sig);
return this._secret.encodeDER(sig);
};

View File

@@ -69,13 +69,15 @@ Log.prototype.error = Log.makeLevel(4);
*/
function getLogInfo(message, args) {
var stack = new Error().stack;
return [
// Timestamp
'[' + new Date().toISOString() + ']',
message,
'--',
// Location
(new Error()).stack.split('\n')[4].replace(/^\s+/, ''),
(typeof stack === 'string') ? stack.split('\n')[4].replace(/^\s+/, '') : '',
'\n'
].concat(args);
}

View File

@@ -1,4 +1,4 @@
'use strict';
'use strict';
// Interface to manage connections to rippled servers
//
@@ -517,8 +517,13 @@ Remote.prototype.disconnect = function(callback) {
Remote.prototype._handleMessage = function(message, server) {
try {
message = JSON.parse(message);
/*eslint-disable no-empty*/
} catch (e) {
// TODO: why are we suppressing this?
console.error(e);
}
/*eslint-enable no-empty*/
if (!Remote.isValidMessage(message)) {
// Unexpected response from remote.
@@ -548,6 +553,15 @@ Remote.prototype._handleMessage = function(message, server) {
}
};
Remote.prototype.getLedgerSequence = function() {
if (!this._ledger_current_index) {
throw new Error('Ledger sequence has not yet been initialized');
}
return this._ledger_current_index;
};
/**
* Handle server ledger_closed event
*

View File

@@ -1,18 +1,19 @@
'use strict';
//
// Seed support
//
var extend = require('extend');
var utils = require('./utils');
var sjcl = utils.sjcl;
var utils = require('./utils');
var sjcl = utils.sjcl;
var Base = require('./base').Base;
var UInt = require('./uint').UInt;
var UInt256 = require('./uint256').UInt256;
var Base = require('./base').Base;
var UInt = require('./uint').UInt;
var UInt160 = require('./uint160').UInt160;
var KeyPair = require('./keypair').KeyPair;
var Seed = extend(function () {
var Seed = extend(function() {
this._curve = sjcl.ecc.curves.k256;
this._value = NaN;
}, UInt);
@@ -23,7 +24,7 @@ Seed.prototype.constructor = Seed;
// value = NaN on error.
// One day this will support rfc1751 too.
Seed.prototype.parse_json = function (j) {
Seed.prototype.parse_json = function(j) {
if (typeof j === 'string') {
if (!j.length) {
this._value = NaN;
@@ -43,7 +44,7 @@ Seed.prototype.parse_json = function (j) {
return this;
};
Seed.prototype.parse_passphrase = function (j) {
Seed.prototype.parse_passphrase = function(j) {
if (typeof j !== 'string') {
throw new Error('Passphrase must be a string');
}
@@ -56,7 +57,7 @@ Seed.prototype.parse_passphrase = function (j) {
return this;
};
Seed.prototype.to_json = function () {
Seed.prototype.to_json = function() {
if (!(this.is_valid())) {
return NaN;
}
@@ -68,20 +69,18 @@ Seed.prototype.to_json = function () {
function append_int(a, i) {
return [].concat(a, i >> 24, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff);
};
}
function firstHalfOfSHA512(bytes) {
return sjcl.bitArray.bitSlice(
sjcl.hash.sha512.hash(sjcl.codec.bytes.toBits(bytes)),
0, 256
);
};
}
function SHA256_RIPEMD160(bits) {
return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits));
};
/**
// Removed a `*` so this JSDoc-ish syntax is ignored.
// This will soon all change anyway.
/*
* @param account
* {undefined} take first, default, KeyPair
*
@@ -92,10 +91,11 @@ function SHA256_RIPEMD160(bits) {
* that is desired.
*
* @param maxLoops (optional)
* {Number} specifies the amount of attempts taken to generate
* a matching KeyPair
* {Number} specifies the amount of attempts taken
* to generate a matching KeyPair
*
*/
Seed.prototype.get_key = function (account, maxLoops) {
Seed.prototype.get_key = function(account, maxLoops) {
var account_number = 0, address;
var max_loops = maxLoops || 1;
@@ -105,7 +105,7 @@ Seed.prototype.get_key = function (account, maxLoops) {
if (account) {
if (typeof account === 'number') {
account_number = account;
max_loops = account_number+1;
max_loops = account_number + 1;
} else {
address = UInt160.from_json(account);
}
@@ -116,7 +116,8 @@ Seed.prototype.get_key = function (account, maxLoops) {
var i = 0;
do {
private_gen = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(this.to_bytes(), i)));
private_gen = sjcl.bn.fromBits(
firstHalfOfSHA512(append_int(this.to_bytes(), i)));
i++;
} while (!curve.r.greaterEquals(private_gen));
@@ -130,7 +131,13 @@ Seed.prototype.get_key = function (account, maxLoops) {
i = 0;
do {
sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), account_number), i)));
sec = sjcl.bn.fromBits(
firstHalfOfSHA512(
append_int(
append_int(public_gen.toBytesCompressed(), account_number)
,
i
)));
i++;
} while (!curve.r.greaterEquals(sec));
@@ -141,12 +148,13 @@ Seed.prototype.get_key = function (account, maxLoops) {
if (max_loops-- <= 0) {
// We are almost certainly looking for an account that would take same
// value of $too_long {forever, ...}
throw new Error('Too many loops looking for KeyPair yielding '+
address.to_json() +' from ' + this.to_json());
throw new Error('Too many loops looking for KeyPair yielding ' +
address.to_json() + ' from ' + this.to_json());
}
} while (address && !key_pair.get_address().equals(address));
return key_pair;
return key_pair;
};
exports.Seed = Seed;

View File

@@ -1,10 +1,12 @@
var _ = require('lodash');
var assert = require('assert');
var extend = require('extend');
'use strict';
var _ = require('lodash');
var assert = require('assert');
var extend = require('extend');
var binformat = require('./binformat');
var stypes = require('./serializedtypes');
var Crypt = require('./crypt').Crypt;
var utils = require('./utils');
var stypes = require('./serializedtypes');
var Crypt = require('./crypt').Crypt;
var utils = require('./utils');
var sjcl = utils.sjcl;
@@ -29,12 +31,14 @@ Object.keys(binformat.ter).forEach(function(key) {
function normalize_sjcl_bn_hex(string) {
var hex = string.slice(2); // remove '0x' prefix
// now strip leading zeros
var i = _.findIndex(hex, function(c) { return c !== '0'; });
var i = _.findIndex(hex, function(c) {
return c !== '0';
});
return i >= 0 ? hex.slice(i) : '0';
}
function SerializedObject(buf) {
if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf)) ) {
if (Array.isArray(buf) || (Buffer && Buffer.isBuffer(buf))) {
this.buffer = buf;
} else if (typeof buf === 'string') {
this.buffer = sjcl.codec.bytes.fromBits(sjcl.codec.hex.toBits(buf));
@@ -49,7 +53,7 @@ function SerializedObject(buf) {
SerializedObject.from_json = function(obj) {
// Create a copy of the object so we don't modify it
obj = extend(true, {}, obj);
var so = new SerializedObject();
var so = new SerializedObject();
var typedef;
if (typeof obj.TransactionType === 'number') {
@@ -107,7 +111,7 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
var field = spec[0];
var requirement = spec[1];
if (binformat.REQUIRED === requirement && obj[field] === void(0)) {
if (binformat.REQUIRED === requirement && obj[field] === undefined) {
missing_fields.push(field);
}
}
@@ -115,9 +119,9 @@ SerializedObject.check_no_missing_fields = function(typedef, obj) {
if (missing_fields.length > 0) {
var object_name;
if (obj.TransactionType !== void(0)) {
if (obj.TransactionType !== undefined) {
object_name = SerializedObject.lookup_type_tx(obj.TransactionType);
} else if (obj.LedgerEntryType != null){
} else if (obj.LedgerEntryType !== undefined) {
object_name = SerializedObject.lookup_type_le(obj.LedgerEntryType);
} else {
object_name = 'TransactionMetaData';
@@ -133,7 +137,17 @@ SerializedObject.prototype.append = function(bytes) {
bytes = bytes.buffer;
}
this.buffer = this.buffer.concat(bytes);
// Make sure both buffer and bytes are Array. Either could potentially be a
// Buffer.
if (Array.isArray(this.buffer) && Array.isArray(bytes)) {
// Array::concat is horribly slow where buffer length is 100 kbytes + One
// transaction with 1100 affected nodes took around 23 seconds to convert
// from json to bytes.
Array.prototype.push.apply(this.buffer, bytes);
} else {
this.buffer = this.buffer.concat(bytes);
}
this.pointer += bytes.length;
};
@@ -216,14 +230,17 @@ SerializedObject.jsonify_structure = function(structure, field_name) {
if (typeof structure.to_json === 'function') {
output = structure.to_json();
} else if (structure instanceof sjcl.bn) {
output = ('0000000000000000' + normalize_sjcl_bn_hex(structure.toString()).toUpperCase()).slice(-16);
output = ('0000000000000000' +
normalize_sjcl_bn_hex(structure.toString())
.toUpperCase()
).slice(-16);
} else {
//new Array or Object
// new Array or Object
output = new structure.constructor();
var keys = Object.keys(structure);
for (var i=0, l=keys.length; i<l; i++) {
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i];
output[key] = SerializedObject.jsonify_structure(structure[key], key);
}
@@ -256,7 +273,7 @@ SerializedObject.prototype.hash = function(prefix) {
var sign_buffer = new SerializedObject();
// Add hashing prefix
if ('undefined' !== typeof prefix) {
if (typeof prefix !== 'undefined') {
stypes.Int32.serialize(sign_buffer, prefix);
}
@@ -272,17 +289,11 @@ SerializedObject.prototype.hash = function(prefix) {
SerializedObject.prototype.signing_hash = SerializedObject.prototype.hash;
SerializedObject.prototype.serialize_field = function(spec, obj) {
var name = spec[0];
var name = spec[0];
var presence = spec[1];
var field_id = spec[2];
var Type = stypes[spec[3]];
if (typeof obj[name] !== 'undefined') {
// ST: Old serialization code
//this.append(SerializedObject.get_field_header(Type.id, field_id));
try {
// ST: Old serialization code
//Type.serialize(this, obj[name]);
stypes.serialize(this, name, obj[name]);
} catch (e) {
// Add field name to message and rethrow
@@ -295,7 +306,7 @@ SerializedObject.prototype.serialize_field = function(spec, obj) {
};
SerializedObject.get_field_header = function(type_id, field_id) {
var buffer = [ 0 ];
var buffer = [0];
if (type_id > 0xF) {
buffer.push(type_id & 0xFF);
@@ -328,7 +339,7 @@ SerializedObject.lookup_type_tx = function(id) {
return TRANSACTION_TYPES[id];
};
SerializedObject.lookup_type_le = function (id) {
SerializedObject.lookup_type_le = function(id) {
assert(typeof id === 'number');
return LEDGER_ENTRY_TYPES[id];
};

View File

@@ -1,30 +1,19 @@
'use strict';
var util = require('util');
var sjcl = require('./utils').sjcl;
var stypes = require('./serializedtypes');
var hashprefixes = require('./hashprefixes');
var UInt256 = require('./uint256').UInt256;
var SerializedObject = require('./serializedobject').SerializedObject;
function SHAMap() {
this.root = new SHAMapTreeNodeInner(0);
};
SHAMap.prototype.add_item = function(tag, node, type) {
var node = new SHAMapTreeNodeLeaf(tag, node, type);
this.root.add_item(tag, node);
};
SHAMap.prototype.hash = function() {
return this.root.hash();
};
/**
* Abstract class representing a node in a SHAMap tree.
*
* Can be either SHAMapTreeNodeInner or SHAMapTreeNodeLeaf.
*
* @class
*/
function SHAMapTreeNode() { };
function SHAMapTreeNode() { }
SHAMapTreeNode.TYPE_INNER = 1;
SHAMapTreeNode.TYPE_TRANSACTION_NM = 2;
@@ -32,11 +21,17 @@ SHAMapTreeNode.TYPE_TRANSACTION_MD = 3;
SHAMapTreeNode.TYPE_ACCOUNT_STATE = 4;
/**
* @param tag {String} 64 hexadecimal characters
* @param {String} tag (64 hexadecimal characters)
* @param {SHAMapTreeNode} node
* @return {void}
* @virtual
*/
/*eslint-disable no-unused-vars*/
SHAMapTreeNode.prototype.add_item = function(tag, node) {
throw new Error('Called unimplemented virtual method SHAMapTreeNode#add_item.');
throw new Error(
'Called unimplemented virtual method SHAMapTreeNode#add_item.');
};
/*eslint-enable no-unused-vars*/
SHAMapTreeNode.prototype.hash = function() {
throw new Error('Called unimplemented virtual method SHAMapTreeNode#hash.');
@@ -44,6 +39,8 @@ SHAMapTreeNode.prototype.hash = function() {
/**
* Inner (non-leaf) node in a SHAMap tree.
* @param {Number} depth (i.e. how many parent inner nodes)
* @class
*/
function SHAMapTreeNodeInner(depth) {
SHAMapTreeNode.call(this);
@@ -51,7 +48,7 @@ function SHAMapTreeNodeInner(depth) {
this.leaves = {};
this.type = SHAMapTreeNode.INNER;
this.depth = depth == null ? 0 : depth;
this.depth = depth === undefined ? 0 : depth;
this.empty = true;
}
@@ -59,9 +56,11 @@ function SHAMapTreeNodeInner(depth) {
util.inherits(SHAMapTreeNodeInner, SHAMapTreeNode);
/**
* @param tag {String} (equates to a ledger entries `index`)
* @param {String} tag (equates to a ledger entry `index`)
* @param {SHAMapTreeNode} node (to add)
* @return {void}
*/
SHAMapTreeNodeInner.prototype.add_item = function (tag, node) {
SHAMapTreeNodeInner.prototype.add_item = function(tag, node) {
var depth = this.depth;
var existing_node = this.get_node(tag[depth]);
@@ -72,7 +71,8 @@ SHAMapTreeNodeInner.prototype.add_item = function (tag, node) {
existing_node.add_item(tag, node);
} else if (existing_node.tag === tag) {
// Collision
throw new Error('Tried to add a node to a SHAMap that was already in there.');
throw new Error(
'Tried to add a node to a SHAMap that was already in there.');
} else {
// Turn it into an inner node
var new_inner_node = new SHAMapTreeNodeInner(depth + 1);
@@ -92,6 +92,9 @@ SHAMapTreeNodeInner.prototype.add_item = function (tag, node) {
/**
* Overwrite the node that is currently in a given slot.
* @param {String} slot (a character 0-F)
* @param {SHAMapTreeNode} node (to place)
* @return {void}
*/
SHAMapTreeNodeInner.prototype.set_node = function(slot, node) {
this.leaves[slot] = node;
@@ -108,9 +111,8 @@ SHAMapTreeNodeInner.prototype.hash = function() {
}
var hash_buffer = new SerializedObject();
var buffer = [ ];
for (var i=0; i<16; i++) {
for (var i = 0; i < 16; i++) {
var leafHash = UInt256.from_hex(UInt256.HEX_ZERO);
var slot = i.toString(16).toUpperCase();
@@ -128,6 +130,10 @@ SHAMapTreeNodeInner.prototype.hash = function() {
/**
* Leaf node in a SHAMap tree.
* @param {String} tag (equates to a ledger entry `index`)
* @param {SerializedObject} node (bytes of account state, transaction etc)
* @param {Number} type (one of TYPE_ACCOUNT_STATE, TYPE_TRANSACTION_MD etc)
* @class
*/
function SHAMapTreeNodeLeaf(tag, node, type) {
SHAMapTreeNode.call(this);
@@ -140,11 +146,11 @@ function SHAMapTreeNodeLeaf(tag, node, type) {
this.tag_bytes = UInt256.from_hex(this.tag).to_bytes();
this.type = type;
this.node = node;
};
}
util.inherits(SHAMapTreeNodeLeaf, SHAMapTreeNode);
SHAMapTreeNodeLeaf.prototype.hash = function () {
SHAMapTreeNodeLeaf.prototype.hash = function() {
var buffer = new SerializedObject();
switch (this.type) {
case SHAMapTreeNode.TYPE_ACCOUNT_STATE:
@@ -162,6 +168,19 @@ SHAMapTreeNodeLeaf.prototype.hash = function () {
}
};
function SHAMap() {
this.root = new SHAMapTreeNodeInner(0);
}
SHAMap.prototype.add_item = function(tag, node, type) {
node = new SHAMapTreeNodeLeaf(tag, node, type);
this.root.add_item(tag, node);
};
SHAMap.prototype.hash = function() {
return this.root.hash();
};
exports.SHAMap = SHAMap;
exports.SHAMapTreeNode = SHAMapTreeNode;
exports.SHAMapTreeNodeInner = SHAMapTreeNodeInner;

View File

@@ -1,17 +1,18 @@
var util = require('util');
var assert = require('assert');
var EventEmitter = require('events').EventEmitter;
var utils = require('./utils');
var sjcl = require('./utils').sjcl;
var Amount = require('./amount').Amount;
var Currency = require('./amount').Currency;
var UInt160 = require('./amount').UInt160;
var Seed = require('./seed').Seed;
'use strict';
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var utils = require('./utils');
var sjcl = require('./utils').sjcl;
var Amount = require('./amount').Amount;
var Currency = require('./amount').Currency;
var UInt160 = require('./amount').UInt160;
var Seed = require('./seed').Seed;
var SerializedObject = require('./serializedobject').SerializedObject;
var RippleError = require('./rippleerror').RippleError;
var hashprefixes = require('./hashprefixes');
var config = require('./config');
var log = require('./log').internal.sub('transaction');
var RippleError = require('./rippleerror').RippleError;
var hashprefixes = require('./hashprefixes');
var config = require('./config');
var log = require('./log').internal.sub('transaction');
/**
* @constructor Transaction
@@ -35,14 +36,14 @@ function Transaction(remote) {
var remoteExists = (typeof remote === 'object');
this.remote = remote;
this.tx_json = { Flags: 0 };
this._secret = void(0);
this.tx_json = {Flags: 0};
this._secret = undefined;
this._build_path = false;
this._maxFee = remoteExists ? this.remote.max_fee : void(0);
this._maxFee = remoteExists ? this.remote.max_fee : undefined;
this.state = 'unsubmitted';
this.finalized = false;
this.previousSigningHash = void(0);
this.submitIndex = void(0);
this.previousSigningHash = undefined;
this.submitIndex = undefined;
this.canonical = remoteExists ? this.remote.canonical_signing : true;
this.submittedIDs = [ ];
this.attempts = 0;
@@ -76,11 +77,12 @@ function Transaction(remote) {
// Transaction was submitted successfully to the network
self.setState('pending');
});
};
}
util.inherits(Transaction, EventEmitter);
// XXX This needs to be determined from the network.
// This is currently a constant in rippled known as the "base reference"
// https://wiki.ripple.com/Transaction_Fee#Base_Fees
Transaction.fee_units = {
default: 10
};
@@ -88,38 +90,38 @@ Transaction.fee_units = {
Transaction.flags = {
// Universal flags can apply to any transaction type
Universal: {
FullyCanonicalSig: 0x80000000
FullyCanonicalSig: 0x80000000
},
AccountSet: {
RequireDestTag: 0x00010000,
OptionalDestTag: 0x00020000,
RequireAuth: 0x00040000,
OptionalAuth: 0x00080000,
DisallowXRP: 0x00100000,
AllowXRP: 0x00200000
RequireDestTag: 0x00010000,
OptionalDestTag: 0x00020000,
RequireAuth: 0x00040000,
OptionalAuth: 0x00080000,
DisallowXRP: 0x00100000,
AllowXRP: 0x00200000
},
TrustSet: {
SetAuth: 0x00010000,
NoRipple: 0x00020000,
SetNoRipple: 0x00020000,
ClearNoRipple: 0x00040000,
SetFreeze: 0x00100000,
ClearFreeze: 0x00200000
SetAuth: 0x00010000,
NoRipple: 0x00020000,
SetNoRipple: 0x00020000,
ClearNoRipple: 0x00040000,
SetFreeze: 0x00100000,
ClearFreeze: 0x00200000
},
OfferCreate: {
Passive: 0x00010000,
ImmediateOrCancel: 0x00020000,
FillOrKill: 0x00040000,
Sell: 0x00080000
Passive: 0x00010000,
ImmediateOrCancel: 0x00020000,
FillOrKill: 0x00040000,
Sell: 0x00080000
},
Payment: {
NoRippleDirect: 0x00010000,
PartialPayment: 0x00020000,
LimitQuality: 0x00040000
NoRippleDirect: 0x00010000,
PartialPayment: 0x00020000,
LimitQuality: 0x00040000
}
};
@@ -128,14 +130,14 @@ Transaction.flags = {
// SetFlag or ClearFlag field
Transaction.set_clear_flags = {
AccountSet: {
asfRequireDest: 1,
asfRequireAuth: 2,
asfDisallowXRP: 3,
asfDisableMaster: 4,
asfAccountTxnID: 5,
asfNoFreeze: 6,
asfGlobalFreeze: 7,
asfDefaultRipple: 8
asfRequireDest: 1,
asfRequireAuth: 2,
asfDisallowXRP: 3,
asfDisableMaster: 4,
asfAccountTxnID: 5,
asfNoFreeze: 6,
asfGlobalFreeze: 7,
asfDefaultRipple: 8
}
};
@@ -147,12 +149,12 @@ Transaction.ASCII_REGEX = /^[\x00-\x7F]*$/;
Transaction.formats = require('./binformat').tx;
Transaction.prototype.consts = {
telLOCAL_ERROR: -399,
temMALFORMED: -299,
tefFAILURE: -199,
terRETRY: -99,
tesSUCCESS: 0,
tecCLAIMED: 100
telLOCAL_ERROR: -399,
temMALFORMED: -299,
tefFAILURE: -199,
terRETRY: -99,
tesSUCCESS: 0,
tecCLAIMED: 100
};
Transaction.prototype.isTelLocal = function(ter) {
@@ -180,7 +182,9 @@ Transaction.prototype.isTecClaimed = function(ter) {
};
Transaction.prototype.isRejected = function(ter) {
return this.isTelLocal(ter) || this.isTemMalformed(ter) || this.isTefFailure(ter);
return this.isTelLocal(ter) ||
this.isTemMalformed(ter) ||
this.isTefFailure(ter);
};
Transaction.from_json = function(j) {
@@ -217,7 +221,7 @@ Transaction.prototype.finalize = function(message) {
if (this.result) {
this.result.ledger_index = message.ledger_index;
this.result.ledger_hash = message.ledger_hash;
this.result.ledger_hash = message.ledger_hash;
} else {
this.result = message;
this.result.tx_json = this.tx_json;
@@ -263,7 +267,7 @@ Transaction.prototype.getTransactionType = function() {
Transaction.prototype.getManager = function(account) {
if (!this.remote) {
return void(0);
return undefined;
}
if (!account) {
@@ -282,7 +286,7 @@ Transaction.prototype.getManager = function(account) {
Transaction.prototype.getSecret =
Transaction.prototype._accountSecret = function(account) {
if (!this.remote) {
return void(0);
return undefined;
}
if (!account) {
@@ -306,7 +310,7 @@ Transaction.prototype._accountSecret = function(account) {
Transaction.prototype._getFeeUnits =
Transaction.prototype.feeUnits = function() {
return Transaction.fee_units['default'];
return Transaction.fee_units.default;
};
/**
@@ -317,13 +321,13 @@ Transaction.prototype.feeUnits = function() {
Transaction.prototype._computeFee = function() {
if (!this.remote) {
return void(0);
return undefined;
}
var servers = this.remote._servers;
var fees = [ ];
for (var i=0; i<servers.length; i++) {
for (var i = 0; i < servers.length; i++) {
var server = servers[i];
if (server._connected) {
fees.push(Number(server._computeFee(this._getFeeUnits())));
@@ -331,7 +335,7 @@ Transaction.prototype._computeFee = function() {
}
switch (fees.length) {
case 0: return;
case 0: return undefined;
case 1: return String(fees[0]);
}
@@ -340,9 +344,8 @@ Transaction.prototype._computeFee = function() {
return 1;
} else if (a < b) {
return -1;
} else {
return 0;
}
return 0;
});
var midInd = Math.floor(fees.length / 2);
@@ -374,8 +377,12 @@ Transaction.prototype.complete = function() {
}
}
if (!this._secret) {
this._secret = this.getSecret();
}
// Try to auto-fill the secret
if (!this._secret && !(this._secret = this.getSecret())) {
if (!this._secret) {
this.emit('error', new RippleError('tejSecretUnknown', 'Missing secret'));
return false;
}
@@ -383,7 +390,7 @@ Transaction.prototype.complete = function() {
if (typeof this.tx_json.SigningPubKey === 'undefined') {
try {
var seed = Seed.from_json(this._secret);
var key = seed.get_key(this.tx_json.Account);
var key = seed.get_key(this.tx_json.Account);
this.tx_json.SigningPubKey = key.to_hex_pub();
} catch(e) {
this.emit('error', new RippleError(
@@ -396,7 +403,8 @@ Transaction.prototype.complete = function() {
// an assigned server
if (this.remote && typeof this.tx_json.Fee === 'undefined') {
if (this.remote.local_fee || !this.remote.trusted) {
if (!(this.tx_json.Fee = this._computeFee())) {
this.tx_json.Fee = this._computeFee();
if (!this.tx_json.Fee) {
this.emit('error', new RippleError('tejUnconnected'));
return false;
}
@@ -459,7 +467,7 @@ Transaction.prototype.sign = function() {
}
var key = seed.get_key(this.tx_json.Account);
var sig = key.sign(hash, 0);
var sig = key.sign(hash);
var hex = sjcl.codec.hex.fromBits(sig).toUpperCase();
this.tx_json.TxnSignature = hex;
@@ -494,7 +502,7 @@ Transaction.prototype.addId = function(id) {
Transaction.prototype.findId = function(cache) {
var result;
for (var i=0; i<this.submittedIDs.length; i++) {
for (var i = 0; i < this.submittedIDs.length; i++) {
var hash = this.submittedIDs[i];
if ((result = cache[hash])) {
break;
@@ -629,7 +637,7 @@ Transaction.prototype.maxFee = function(fee) {
};
/*
* Set the fee user will pay to the network for submitting this transaction.
* Set the fee user will pay to the network for submitting this transaction.
* Specified fee must be >= 0.
*
* @param {Number} fee The proposed fee
@@ -716,7 +724,7 @@ Transaction.prototype.pathAdd = function(path) {
Transaction.prototype.setPaths =
Transaction.prototype.paths = function(paths) {
if (Array.isArray(paths)) {
for (var i=0, l=paths.length; i<l; i++) {
for (var i = 0, l = paths.length; i < l; i++) {
this.addPath(paths[i]);
}
}
@@ -778,7 +786,7 @@ Transaction.prototype.transferRate = function(rate) {
*/
Transaction.prototype.setFlags = function(flags) {
if (flags === void(0)) {
if (flags === undefined) {
return this;
}
@@ -790,7 +798,7 @@ Transaction.prototype.setFlags = function(flags) {
var transaction_flags = Transaction.flags[this.getTransactionType()] || { };
var flag_set = Array.isArray(flags) ? flags : [].slice.call(arguments);
for (var i=0, l=flag_set.length; i<l; i++) {
for (var i = 0, l = flag_set.length; i < l; i++) {
var flag = flag_set[i];
if (transaction_flags.hasOwnProperty(flag)) {
@@ -845,8 +853,8 @@ Transaction.prototype.addMemo = function(memoType, memoFormat, memoData) {
if (memoType) {
if (Transaction.MEMO_TYPES[memoType]) {
//XXX Maybe in the future we want a schema validator for
//memo types
// XXX Maybe in the future we want a schema validator for
// memo types
memoType = Transaction.MEMO_TYPES[memoType];
}
memo.MemoType = convertStringToHex(memoType);
@@ -862,17 +870,19 @@ Transaction.prototype.addMemo = function(memoType, memoFormat, memoData) {
try {
memoData = JSON.stringify(memoData);
} catch (e) {
throw new Error('MemoFormat json with invalid JSON in MemoData field');
throw new Error(
'MemoFormat json with invalid JSON in MemoData field');
}
} else {
throw new Error('MemoData can only be a JSON object with a valid json MemoFormat');
throw new Error(
'MemoData can only be a JSON object with a valid json MemoFormat');
}
}
memo.MemoData = convertStringToHex(memoData);
}
this.tx_json.Memos = (this.tx_json.Memos || []).concat({ Memo: memo });
this.tx_json.Memos = (this.tx_json.Memos || []).concat({Memo: memo});
return this;
};
@@ -917,23 +927,33 @@ Transaction.prototype.accountSet = function(src, set_flag, clear_flag) {
throw new Error('Source address invalid');
}
this.tx_json.TransactionType= 'AccountSet';
this.tx_json.TransactionType = 'AccountSet';
this.tx_json.Account = UInt160.json_rewrite(src);
var SetClearFlags = Transaction.set_clear_flags.AccountSet;
function prepareFlag(flag) {
return (typeof flag === 'number')
? flag
? flag
: (SetClearFlags[flag] || SetClearFlags['asf' + flag]);
};
if (set_flag && (set_flag = prepareFlag(set_flag))) {
this.tx_json.SetFlag = set_flag;
}
if (clear_flag && (clear_flag = prepareFlag(clear_flag))) {
this.tx_json.ClearFlag = clear_flag;
var prepared;
if (set_flag) {
prepared = prepareFlag(set_flag);
if (prepared) {
this.tx_json.SetFlag = prepared;
}
}
if (clear_flag) {
prepared = prepareFlag(clear_flag);
if (prepared) {
this.tx_json.ClearFlag = prepared;
}
}
return this;
@@ -995,7 +1015,8 @@ Transaction.prototype.offerCancel = function(src, sequence) {
* @param [Number] sequence of an existing offer to replace
*/
Transaction.prototype.offerCreate = function(src, taker_pays, taker_gets, expiration, cancel_sequence) {
Transaction.prototype.offerCreate = function(src, taker_pays, taker_gets,
expiration, cancel_sequence) {
if (typeof src === 'object') {
var options = src;
cancel_sequence = options.cancel_sequence || options.sequence;
@@ -1111,7 +1132,10 @@ Transaction.prototype.payment = function(src, dst, amount) {
*/
Transaction.prototype.trustSet =
Transaction.prototype.rippleLineSet = function(src, limit, quality_in, quality_out) {
Transaction.prototype.rippleLineSet = function(src,
limit,
quality_in,
quality_out) {
if (typeof src === 'object') {
var options = src;
quality_out = options.quality_out;
@@ -1127,7 +1151,7 @@ Transaction.prototype.rippleLineSet = function(src, limit, quality_in, quality_o
this.tx_json.TransactionType = 'TrustSet';
this.tx_json.Account = UInt160.json_rewrite(src);
if (limit !== void(0)) {
if (limit !== undefined) {
this.tx_json.LimitAmount = Amount.json_rewrite(limit);
}
@@ -1153,7 +1177,7 @@ Transaction.prototype.rippleLineSet = function(src, limit, quality_in, quality_o
Transaction.prototype.submit = function(callback) {
var self = this;
this.callback = (typeof callback === 'function') ? callback : function(){};
this.callback = (typeof callback === 'function') ? callback : function() {};
this._errorHandler = function transactionError(error, message) {
if (!(error instanceof RippleError)) {
@@ -1168,7 +1192,7 @@ Transaction.prototype.submit = function(callback) {
if (!this.remote) {
this.emit('error', new Error('No remote found'));
return;
return this;
}
this.getManager().submit(this);
@@ -1198,7 +1222,7 @@ Transaction.prototype.summary = function() {
initialSubmitIndex: this.initialSubmitIndex,
lastLedgerSequence: this.lastLedgerSequence,
state: this.state,
server: this._server ? this._server._opts.url : void(0),
server: this._server ? this._server._opts.url : undefined,
finalized: this.finalized
};

View File

@@ -1,6 +1,10 @@
var utils = require('./utils');
var sjcl = utils.sjcl;
var config = require('./config');
'use strict';
/*eslint new-cap: 1*/
var utils = require('./utils');
var sjcl = utils.sjcl;
var config = require('./config');
//
// Abstract UInt class
@@ -8,11 +12,11 @@ var config = require('./config');
// Base class for UInt classes
//
var UInt = function() {
function UInt() {
// Internal form: NaN or sjcl.bn
this._value = NaN;
this._value = NaN;
this._update();
};
}
UInt.json_rewrite = function(j, opts) {
return this.from_json(j).to_json(opts);
@@ -22,63 +26,56 @@ UInt.json_rewrite = function(j, opts) {
UInt.from_generic = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_generic(j);
}
return (new this()).parse_generic(j);
};
// Return a new UInt from j.
UInt.from_hex = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_hex(j);
}
return (new this()).parse_hex(j);
};
// Return a new UInt from j.
UInt.from_json = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_json(j);
}
return (new this()).parse_json(j);
};
// Return a new UInt from j.
UInt.from_bits = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_bits(j);
}
return (new this()).parse_bits(j);
};
// Return a new UInt from j.
UInt.from_bytes = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_bytes(j);
}
return (new this()).parse_bytes(j);
};
// Return a new UInt from j.
UInt.from_bn = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_bn(j);
}
return (new this()).parse_bn(j);
};
// Return a new UInt from j.
UInt.from_number = function(j) {
if (j instanceof this) {
return j.clone();
} else {
return (new this()).parse_number(j);
}
return (new this()).parse_number(j);
};
UInt.is_valid = function(j) {
@@ -93,7 +90,7 @@ UInt.prototype.clone = function() {
UInt.prototype.copyTo = function(d) {
d._value = this._value;
if (this._version_byte !== void(0)) {
if (this._version_byte !== undefined) {
d._version_byte = this._version_byte;
}
@@ -125,6 +122,8 @@ UInt.prototype.is_zero = function() {
*
* The reason for keeping this mechanism in this class is so every subclass can
* call it whenever it modifies the internal state.
*
* @return {void}
*/
UInt.prototype._update = function() {
// Nothing to do by default. Subclasses will override this.
@@ -137,33 +136,34 @@ UInt.prototype.parse_generic = function(j) {
j = config.accounts[j].account;
}
switch (j) {
case undefined:
case '0':
case this.constructor.STR_ZERO:
case this.constructor.ACCOUNT_ZERO:
case this.constructor.HEX_ZERO:
this._value = new sjcl.bn(0);
case '0':
case this.constructor.STR_ZERO:
case this.constructor.ACCOUNT_ZERO:
case this.constructor.HEX_ZERO:
this._value = new sjcl.bn(0);
break;
case '1':
case this.constructor.STR_ONE:
case this.constructor.ACCOUNT_ONE:
case this.constructor.HEX_ONE:
this._value = new sjcl.bn(1);
case this.constructor.STR_ONE:
case this.constructor.ACCOUNT_ONE:
case this.constructor.HEX_ONE:
this._value = new sjcl.bn(1);
break;
default:
if (typeof j !== 'string') {
this._value = NaN;
this._value = NaN;
} else if (this.constructor.width === j.length) {
var hex = utils.arrayToHex(utils.stringToArray(j));
this._value = new sjcl.bn(hex, 16);
this._value = new sjcl.bn(hex, 16);
} else if ((this.constructor.width * 2) === j.length) {
// XXX Check char set!
this._value = new sjcl.bn(j, 16);
this._value = new sjcl.bn(j, 16);
} else {
this._value = NaN;
this._value = NaN;
}
}
@@ -204,7 +204,7 @@ UInt.prototype.parse_bytes = function(j) {
this._value = NaN;
} else {
var bits = sjcl.codec.bytes.toBits(j);
this._value = sjcl.bn.fromBits(bits);
this._value = sjcl.bn.fromBits(bits);
}
this._update();
@@ -216,9 +216,8 @@ UInt.prototype.parse_bytes = function(j) {
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) {
// var bytes = sjcl.codec.bytes.fromBits(j.toBits());
// this._value = new sjcl.bn(utils.arrayToHex(bytes), 16);
if ((j instanceof sjcl.bn) &&
j.bitLength() <= this.constructor.width * 8) {
this._value = new sjcl.bn(j);
} else {
this._value = NaN;

View File

@@ -1,13 +1,15 @@
var utils = require('./utils');
'use strict';
var utils = require('./utils');
var extend = require('extend');
var UInt = require('./uint').UInt;
var UInt = require('./uint').UInt;
//
// UInt128 support
//
var UInt128 = extend(function () {
this._value = NaN;
var UInt128 = extend(function() {
this._value = NaN;
}, UInt);
UInt128.width = 16;
@@ -15,8 +17,9 @@ UInt128.prototype = extend({}, UInt.prototype);
UInt128.prototype.constructor = UInt128;
var HEX_ZERO = UInt128.HEX_ZERO = '00000000000000000000000000000000';
var HEX_ONE = UInt128.HEX_ONE = '00000000000000000000000000000000';
var STR_ZERO = UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);
var STR_ONE = UInt128.STR_ONE = utils.hexToString(HEX_ONE);
var HEX_ONE = UInt128.HEX_ONE = '00000000000000000000000000000000';
UInt128.STR_ZERO = utils.hexToString(HEX_ZERO);
UInt128.STR_ONE = utils.hexToString(HEX_ONE);
exports.UInt128 = UInt128;

View File

@@ -1,6 +1,8 @@
var utils = require('./utils');
var config = require('./config');
var extend = require('extend');
'use strict';
var utils = require('./utils');
var config = require('./config');
var extend = require('extend');
var UInt = require('./uint').UInt;
var Base = require('./base').Base;
@@ -10,8 +12,8 @@ var Base = require('./base').Base;
//
var UInt160 = extend(function() {
this._value = NaN;
this._version_byte = void(0);
this._value = NaN;
this._version_byte = undefined;
this._update();
}, UInt);
@@ -19,12 +21,13 @@ UInt160.width = 20;
UInt160.prototype = extend({}, UInt.prototype);
UInt160.prototype.constructor = UInt160;
var ACCOUNT_ZERO = UInt160.ACCOUNT_ZERO = 'rrrrrrrrrrrrrrrrrrrrrhoLvTp';
var ACCOUNT_ONE = UInt160.ACCOUNT_ONE = 'rrrrrrrrrrrrrrrrrrrrBZbvji';
var HEX_ZERO = UInt160.HEX_ZERO = '0000000000000000000000000000000000000000';
var HEX_ONE = UInt160.HEX_ONE = '0000000000000000000000000000000000000001';
var STR_ZERO = UInt160.STR_ZERO = utils.hexToString(HEX_ZERO);
var STR_ONE = UInt160.STR_ONE = utils.hexToString(HEX_ONE);
var HEX_ZERO = UInt160.HEX_ZERO = '0000000000000000000000000000000000000000';
var HEX_ONE = UInt160.HEX_ONE = '0000000000000000000000000000000000000001';
UInt160.ACCOUNT_ZERO = 'rrrrrrrrrrrrrrrrrrrrrhoLvTp';
UInt160.ACCOUNT_ONE = 'rrrrrrrrrrrrrrrrrrrrBZbvji';
UInt160.STR_ZERO = utils.hexToString(HEX_ZERO);
UInt160.STR_ONE = utils.hexToString(HEX_ONE);
UInt160.prototype.set_version = function(j) {
this._version_byte = j;
@@ -78,7 +81,7 @@ UInt160.prototype.parse_generic = function(j) {
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
UInt160.prototype.to_json = function(opts) {
opts = opts || {};
opts = opts || {};
if (this.is_valid()) {
// If this value has a type, return a Base58 encoded string.
@@ -90,9 +93,8 @@ UInt160.prototype.to_json = function(opts) {
}
return output;
} else {
return this.to_hex();
}
return this.to_hex();
}
return NaN;
};

View File

@@ -1,6 +1,8 @@
var utils = require('./utils');
'use strict';
var utils = require('./utils');
var extend = require('extend');
var UInt = require('./uint').UInt;
var UInt = require('./uint').UInt;
//
// UInt256 support
@@ -14,9 +16,13 @@ UInt256.width = 32;
UInt256.prototype = extend({}, UInt.prototype);
UInt256.prototype.constructor = UInt256;
var HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' + '00000000000000000000000000000000';
var HEX_ONE = UInt256.HEX_ONE = '00000000000000000000000000000000' + '00000000000000000000000000000001';
var STR_ZERO = UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);
var STR_ONE = UInt256.STR_ONE = utils.hexToString(HEX_ONE);
var HEX_ZERO = UInt256.HEX_ZERO = '00000000000000000000000000000000' +
'00000000000000000000000000000000';
var HEX_ONE = UInt256.HEX_ONE = '00000000000000000000000000000000' +
'00000000000000000000000000000001';
UInt256.STR_ZERO = utils.hexToString(HEX_ZERO);
UInt256.STR_ONE = utils.hexToString(HEX_ONE);
exports.UInt256 = UInt256;

View File

@@ -1,3 +1,4 @@
'use strict';
function getMantissaDecimalString(bignum) {
var mantissa = bignum.toPrecision(16)
@@ -10,37 +11,22 @@ function getMantissaDecimalString(bignum) {
return mantissa;
}
function filterErr(code, done) {
return function(e) {
done(e.code !== code ? e : void(0));
};
};
function throwErr(done) {
return function(e) {
if (e) {
throw e;
}
done();
};
};
function trace(comment, func) {
return function() {
console.log('%s: %s', trace, arguments.toString);
func(arguments);
};
};
}
function arraySet(count, value) {
var a = new Array(count);
for (var i=0; i<count; i++) {
for (var i = 0; i < count; i++) {
a[i] = value;
}
return a;
};
}
function hexToString(h) {
var a = [];
@@ -51,35 +37,35 @@ function hexToString(h) {
i = 1;
}
for (; i<h.length; i+=2) {
a.push(String.fromCharCode(parseInt(h.substring(i, i+2), 16)));
for (; i < h.length; i += 2) {
a.push(String.fromCharCode(parseInt(h.substring(i, i + 2), 16)));
}
return a.join('');
};
}
function stringToHex(s) {
var result = '';
for (var i=0; i<s.length; i++) {
for (var i = 0; i < s.length; i++) {
var b = s.charCodeAt(i);
result += b < 16 ? '0' + b.toString(16) : b.toString(16);
}
return result;
};
}
function stringToArray(s) {
var a = new Array(s.length);
for (var i=0; i<a.length; i+=1) {
for (var i = 0; i < a.length; i += 1) {
a[i] = s.charCodeAt(i);
}
return a;
};
}
function hexToArray(h) {
return stringToArray(hexToString(h));
};
}
function arrayToHex(a) {
return a.map(function(byteValue) {
@@ -90,7 +76,7 @@ function arrayToHex(a) {
function chunkString(str, n, leftAlign) {
var ret = [];
var i=0, len=str.length;
var i = 0, len = str.length;
if (leftAlign) {
i = str.length % n;
@@ -99,26 +85,27 @@ function chunkString(str, n, leftAlign) {
}
}
for(; i<len; i+=n) {
for (; i < len; i += n) {
ret.push(str.slice(i, n + i));
}
return ret;
};
}
function assert(assertion, msg) {
if (!assertion) {
throw new Error('Assertion failed' + (msg ? ': ' + msg : '.'));
}
};
}
/**
* Return unique values in array.
* @param {Array} arr (values)
* @return {Array} unique values (for string representation of value) in `arr`
*/
function arrayUnique(arr) {
var u = {}, a = [];
for (var i=0, l=arr.length; i<l; i++){
for (var i = 0, l = arr.length; i < l; i++) {
var k = arr[i];
if (u[k]) {
continue;
@@ -128,46 +115,45 @@ function arrayUnique(arr) {
}
return a;
};
}
/**
* Convert a ripple epoch to a JavaScript timestamp.
* @param {Number} rpepoch (seconds since 1/1/2000 GMT)
* @return {Number} ms since unix epoch
*
* JavaScript timestamps are unix epoch in milliseconds.
*/
function toTimestamp(rpepoch) {
return (rpepoch + 0x386D4380) * 1000;
};
}
/**
* Convert a JavaScript timestamp or Date to a Ripple epoch.
*
* JavaScript timestamps are unix epoch in milliseconds.
* @param {Number|Date} timestamp (ms since unix epoch)
* @return {Number} seconds since ripple epoch ( 1/1/2000 GMT)
*/
function fromTimestamp(rpepoch) {
if (rpepoch instanceof Date) {
rpepoch = rpepoch.getTime();
function fromTimestamp(timestamp) {
if (timestamp instanceof Date) {
timestamp = timestamp.getTime();
}
return Math.round(rpepoch / 1000) - 0x386D4380;
};
return Math.round(timestamp / 1000) - 0x386D4380;
}
exports.time = {
fromRipple: toTimestamp,
toRipple: fromTimestamp
};
exports.trace = trace;
exports.arraySet = arraySet;
exports.hexToString = hexToString;
exports.hexToArray = hexToArray;
exports.trace = trace;
exports.arraySet = arraySet;
exports.hexToString = hexToString;
exports.hexToArray = hexToArray;
exports.stringToArray = stringToArray;
exports.stringToHex = stringToHex;
exports.arrayToHex = arrayToHex;
exports.chunkString = chunkString;
exports.assert = assert;
exports.arrayUnique = arrayUnique;
exports.toTimestamp = toTimestamp;
exports.stringToHex = stringToHex;
exports.arrayToHex = arrayToHex;
exports.chunkString = chunkString;
exports.assert = assert;
exports.arrayUnique = arrayUnique;
exports.toTimestamp = toTimestamp;
exports.fromTimestamp = fromTimestamp;
exports.getMantissaDecimalString = getMantissaDecimalString;

View File

@@ -3,6 +3,7 @@
var ws = require('ws');
var lodash = require('lodash');
var assert = require('assert-diff');
var sjcl = require('ripple-lib').sjcl;
var Remote = require('ripple-lib').Remote;
var SerializedObject = require('ripple-lib').SerializedObject;
var Transaction = require('ripple-lib').Transaction;
@@ -42,6 +43,11 @@ describe('TransactionManager', function() {
var account;
var transactionManager;
before(function() {
sjcl.random.addEntropy(
'3045022100A58B0460BC5092CB4F96155C19125A4E079C870663F1D5E8BBC9BD', 256);
});
beforeEach(function(done) {
rippled = new ws.Server({port: 5763});
@@ -51,6 +57,7 @@ describe('TransactionManager', function() {
try {
c.send(JSON.stringify(v));
} catch (e) {
// empty
}
};
c.sendResponse = function(baseResponse, ext) {

View File

@@ -1,9 +1,11 @@
var assert = require('assert');
var Amount = require('ripple-lib').Amount;
var Transaction = require('ripple-lib').Transaction;
/* eslint-disable max-len */
'use strict';
var assert = require('assert');
var Transaction = require('ripple-lib').Transaction;
var TransactionQueue = require('ripple-lib').TransactionQueue;
var Remote = require('ripple-lib').Remote;
var Server = require('ripple-lib').Server;
var Remote = require('ripple-lib').Remote;
var Server = require('ripple-lib').Server;
var sjcl = require('ripple-lib').sjcl;
var transactionResult = {
engine_result: 'tesSUCCESS',
@@ -17,24 +19,30 @@ var transactionResult = {
metadata: {
AffectedNodes: [ ],
TransactionIndex: 0,
TransactionResult: 'tesSUCCESS' },
tx_json: {
Account: 'rHPotLj3CNKaP4bQANcecEuT8hai3VpxfB',
Amount: '1000000',
Destination: 'rYtn3D1VGQyf1MTqcwLDepUKm22YEGXGJA',
Fee: '10',
Flags: 0,
LastLedgerSequence: 7106151,
Sequence: 2973,
SigningPubKey: '0306E9F38DF11402953A5B030C1AE8A88C47E348170C3B8EC6C8D775E797168462',
TransactionType: 'Payment',
TxnSignature: '3045022100A58B0460BC5092CB4F96155C19125A4E079C870663F1D5E8BBC9BDEE06D51F530220408A3AA26988ABF18E16BE77B016F25018A2AA7C99FFE723FC8598471357DBCF',
date: 455660500,
hash: '61D60378AB70ACE630B20A81B50708A3DB5E7CEE35914292FF3761913DA61DEA'
}
TransactionResult: 'tesSUCCESS'
},
tx_json: {
Account: 'rHPotLj3CNKaP4bQANcecEuT8hai3VpxfB',
Amount: '1000000',
Destination: 'rYtn3D1VGQyf1MTqcwLDepUKm22YEGXGJA',
Fee: '10',
Flags: 0,
LastLedgerSequence: 7106151,
Sequence: 2973,
SigningPubKey: '0306E9F38DF11402953A5B030C1AE8A88C47E348170C3B8EC6C8D775E797168462',
TransactionType: 'Payment',
TxnSignature: '3045022100A58B0460BC5092CB4F96155C19125A4E079C870663F1D5E8BBC9BDEE06D51F530220408A3AA26988ABF18E16BE77B016F25018A2AA7C99FFE723FC8598471357DBCF',
date: 455660500,
hash: '61D60378AB70ACE630B20A81B50708A3DB5E7CEE35914292FF3761913DA61DEA'
}
};
describe('Transaction', function() {
before(function() {
sjcl.random.addEntropy(
'3045022100A58B0460BC5092CB4F96155C19125A4E079C870663F1D5E8BBC9BD', 256);
});
it('Success listener', function(done) {
var transaction = new Transaction();
@@ -189,7 +197,7 @@ describe('Transaction', function() {
assert.strictEqual(transaction._accountSecret('rpzT237Ctpaa58KieifoK8RyBmmRwEcfhK'), 'shY1njzHAXp8Qt3bpxYW6RpoZtMKP');
assert.strictEqual(transaction._accountSecret('rpdxPs9CR93eLAc5DTvAgv4S9XJ1CzKj1a'), 'ssboTJezioTq8obyvDU9tVo95NGGQ');
assert.strictEqual(transaction._accountSecret('rExistNot'), void(0));
assert.strictEqual(transaction._accountSecret('rExistNot'), undefined);
});
it('Get fee units', function() {
@@ -220,7 +228,7 @@ describe('Transaction', function() {
s5._connected = true;
s5._load_factor = 256 * 7;
remote._servers = [ s2, s3, s1, s4 ];
remote._servers = [s2, s3, s1, s4];
assert.strictEqual(s1._computeFee(10), '12');
assert.strictEqual(s2._computeFee(10), '48');
@@ -235,7 +243,7 @@ describe('Transaction', function() {
it('Compute fee, no remote', function() {
var transaction = new Transaction();
assert.strictEqual(transaction._computeFee(10), void(0));
assert.strictEqual(transaction._computeFee(10), undefined);
});
it('Compute fee - no connected server', function() {
@@ -252,7 +260,7 @@ describe('Transaction', function() {
s3._connected = false;
s3._load_factor = 256 * 8;
remote._servers = [ s1, s2, s3 ];
remote._servers = [s1, s2, s3];
assert.strictEqual(s1._computeFee(10), '12');
assert.strictEqual(s2._computeFee(10), '48');
@@ -260,7 +268,7 @@ describe('Transaction', function() {
var transaction = new Transaction(remote);
assert.strictEqual(transaction._computeFee(), void(0));
assert.strictEqual(transaction._computeFee(), undefined);
});
it('Compute fee - one connected server', function() {
@@ -277,7 +285,7 @@ describe('Transaction', function() {
s3._connected = true;
s3._load_factor = 256 * 8;
remote._servers = [ s1, s2, s3 ];
remote._servers = [s1, s2, s3];
assert.strictEqual(s1._computeFee(10), '12');
assert.strictEqual(s2._computeFee(10), '48');
@@ -307,7 +315,7 @@ describe('Transaction', function() {
s4._connected = true;
s4._load_factor = 256 * 16;
remote._servers = [ s1, s2, s3, s4 ];
remote._servers = [s1, s2, s3, s4];
assert.strictEqual(s1._computeFee(10), '12');
assert.strictEqual(s2._computeFee(10), '48');
@@ -319,7 +327,7 @@ describe('Transaction', function() {
transaction.tx_json.Sequence = 1;
var src = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh';
var dst = 'rGihwhaqU8g7ahwAvTq6iX5rvsfcbgZw6v';
transaction.payment(src, dst, '100');
remote.set_secret(src, 'masterpassphrase');
@@ -347,7 +355,7 @@ describe('Transaction', function() {
s4._connected = true;
s4._load_factor = 256 * 16;
remote._servers = [ s1, s2, s3, s4 ];
remote._servers = [s1, s2, s3, s4];
assert.strictEqual(s1._computeFee(10), '12');
assert.strictEqual(s2._computeFee(10), '48');
@@ -366,7 +374,7 @@ describe('Transaction', function() {
var s1 = new Server(remote, 'wss://s-west.ripple.com:443');
s1._connected = true;
remote._servers = [ s1 ];
remote._servers = [s1];
remote.trusted = true;
remote.local_signing = true;
@@ -427,7 +435,7 @@ describe('Transaction', function() {
remote.trusted = true;
remote.local_signing = true;
transaction.SigningPubKey = void(0);
transaction.SigningPubKey = undefined;
transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ';
transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoijX';
@@ -465,7 +473,7 @@ describe('Transaction', function() {
var s1 = new Server(remote, 'wss://s-west.ripple.com:443');
s1._connected = true;
remote._servers = [ s1 ];
remote._servers = [s1];
remote.trusted = true;
remote.local_signing = true;
@@ -473,7 +481,7 @@ describe('Transaction', function() {
transaction.tx_json.Account = 'rMWwx3Ma16HnqSd4H6saPisihX9aKpXxHJ';
transaction._secret = 'sh2pTicynUEG46jjR4EoexHcQEoij';
assert.strictEqual(transaction.tx_json.Fee, void(0));
assert.strictEqual(transaction.tx_json.Fee, undefined);
assert(transaction.complete());
@@ -483,13 +491,13 @@ describe('Transaction', function() {
});
it('Complete transaction - compute fee exceeds max fee', function(done) {
var remote = new Remote({ max_fee: 10 });
var remote = new Remote({max_fee: 10});
var s1 = new Server(remote, 'wss://s-west.ripple.com:443');
s1._connected = true;
s1._load_factor = 256 * 16;
remote._servers = [ s1 ];
remote._servers = [s1];
remote.trusted = true;
remote.local_signing = true;
@@ -513,7 +521,7 @@ describe('Transaction', function() {
s1._connected = true;
s1._load_factor = 256;
remote._servers = [ s1 ];
remote._servers = [s1];
remote.trusted = true;
remote.local_signing = true;
@@ -539,7 +547,7 @@ describe('Transaction', function() {
transaction.tx_json.Sequence = 1;
transaction.tx_json.TransactionType = 'AccountSet';
assert.strictEqual(transaction.signingHash(), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE')
assert.strictEqual(transaction.signingHash(), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE');
done();
});
@@ -554,7 +562,7 @@ describe('Transaction', function() {
transaction.tx_json.Sequence = 1;
transaction.tx_json.TransactionType = 'AccountSet';
assert.strictEqual(transaction.hash(), '1A860FC46D1DD9200560C64002418A4E8BBDE939957AC82D7B14D80A1C0E2EB5')
assert.strictEqual(transaction.hash(), '1A860FC46D1DD9200560C64002418A4E8BBDE939957AC82D7B14D80A1C0E2EB5');
done();
});
@@ -569,7 +577,7 @@ describe('Transaction', function() {
transaction.tx_json.Sequence = 1;
transaction.tx_json.TransactionType = 'AccountSet';
assert.strictEqual(transaction.hash('HASH_TX_SIGN'), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE')
assert.strictEqual(transaction.hash('HASH_TX_SIGN'), 'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE');
assert.strictEqual(transaction.hash('HASH_TX_SIGN_TESTNET'), '9FE7D27FC5B9891076B66591F99A683E01E0912986A629235459A3BD1961F341');
done();
@@ -594,51 +602,51 @@ describe('Transaction', function() {
it('Get hash - complex transaction', function() {
var input_json = {
Account : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Amount : {
currency : 'LTC',
issuer : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value : '9.985'
Account: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Amount: {
currency: 'LTC',
issuer: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value: '9.985'
},
Destination : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Fee : '15',
Flags : 0,
Paths : [
Destination: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Fee: '15',
Flags: 0,
Paths: [
[
{
account : 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
currency : 'USD',
issuer : 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
type : 49,
type_hex : '0000000000000031'
account: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
currency: 'USD',
issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
type: 49,
type_hex: '0000000000000031'
},
{
currency : 'LTC',
issuer : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type : 48,
type_hex : '0000000000000030'
currency: 'LTC',
issuer: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type: 48,
type_hex: '0000000000000030'
},
{
account : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
currency : 'LTC',
issuer : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type : 49,
type_hex : '0000000000000031'
account: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
currency: 'LTC',
issuer: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type: 49,
type_hex: '0000000000000031'
}
]
],
SendMax : {
currency : 'USD',
issuer : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value : '30.30993068'
SendMax: {
currency: 'USD',
issuer: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value: '30.30993068'
},
Sequence : 415,
SigningPubKey : '02854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A',
TransactionType : 'Payment',
TxnSignature : '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E'
Sequence: 415,
SigningPubKey: '02854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A',
TransactionType: 'Payment',
TxnSignature: '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E'
};
var expected_hash = "87366146D381AD971B97DD41CFAC1AE4670B0E996AB574B0CE18CE6467811868";
var expected_hash = '87366146D381AD971B97DD41CFAC1AE4670B0E996AB574B0CE18CE6467811868';
var transaction = Transaction.from_json(input_json);
assert.deepEqual(transaction.hash(), expected_hash);
@@ -723,48 +731,48 @@ describe('Transaction', function() {
it('Serialize transaction', function() {
var input_json = {
Account : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Amount : {
currency : 'LTC',
issuer : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value : '9.985'
Account: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Amount: {
currency: 'LTC',
issuer: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value: '9.985'
},
Destination : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Fee : '15',
Flags : 0,
Paths : [
Destination: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
Fee: '15',
Flags: 0,
Paths: [
[
{
account : 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
currency : 'USD',
issuer : 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
type : 49,
type_hex : '0000000000000031'
account: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
currency: 'USD',
issuer: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q',
type: 49,
type_hex: '0000000000000031'
},
{
currency : 'LTC',
issuer : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type : 48,
type_hex : '0000000000000030'
currency: 'LTC',
issuer: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type: 48,
type_hex: '0000000000000030'
},
{
account : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
currency : 'LTC',
issuer : 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type : 49,
type_hex : '0000000000000031'
account: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
currency: 'LTC',
issuer: 'rfYv1TXnwgDDK4WQNbFALykYuEBnrR4pDX',
type: 49,
type_hex: '0000000000000031'
}
]
],
SendMax : {
currency : 'USD',
issuer : 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value : '30.30993068'
SendMax: {
currency: 'USD',
issuer: 'r4qLSAzv4LZ9TLsR7diphGwKnSEAMQTSjS',
value: '30.30993068'
},
Sequence : 415,
SigningPubKey : '02854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A',
TransactionType : 'Payment',
TxnSignature : '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E'
Sequence: 415,
SigningPubKey: '02854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A',
TransactionType: 'Payment',
TxnSignature: '304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E'
};
var expected_hex = '1200002200000000240000019F61D4A3794DFA1510000000000000000000000000004C54430000000000EF7ED76B77750D79EC92A59389952E0E8054407668400000000000000F69D4CAC4AC112283000000000000000000000000005553440000000000EF7ED76B77750D79EC92A59389952E0E80544076732102854B06CE8F3E65323F89260E9E19B33DA3E01B30EA4CA172612DE77973FAC58A7448304602210096C2F385530587DE573936CA51CB86B801A28F777C944E268212BE7341440B7F022100EBF0508A9145A56CDA7FAF314DF3BBE51C6EE450BA7E74D88516891A3608644E8114EF7ED76B77750D79EC92A59389952E0E805440768314EF7ED76B77750D79EC92A59389952E0E80544076011231DD39C650A96EDA48334E70CC4A85B8B2E8502CD30000000000000000000000005553440000000000DD39C650A96EDA48334E70CC4A85B8B2E8502CD3300000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA643147DA9E2E00ECF224A52329793F1BB20FB1B5EA640000000000000000000000004C5443000000000047DA9E2E00ECF224A52329793F1BB20FB1B5EA6400';
@@ -810,8 +818,8 @@ describe('Transaction', function() {
assert.deepEqual(
transaction.submittedIDs,
[ 'F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE',
'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE' ]
['F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE',
'D1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE']
);
done();
@@ -822,7 +830,7 @@ describe('Transaction', function() {
assert.deepEqual(transaction.findId({
F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE: transaction
}), void(0));
}), undefined);
transaction.addId('F1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE');
@@ -832,7 +840,7 @@ describe('Transaction', function() {
assert.strictEqual(transaction.findId({
Z1C15200CF532175F1890B6440AD223D3676140522BC11D2784E56760AE3B4FE: transaction
}), void(0));
}), undefined);
done();
});
@@ -846,7 +854,7 @@ describe('Transaction', function() {
it('Set DestinationTag', function() {
var transaction = new Transaction();
transaction.destinationTag('tag');
assert.strictEqual(transaction.tx_json.DestinationTag, void(0));
assert.strictEqual(transaction.tx_json.DestinationTag, undefined);
transaction.destinationTag(1);
assert.strictEqual(transaction.tx_json.DestinationTag, 1);
});
@@ -855,7 +863,7 @@ describe('Transaction', function() {
var transaction = new Transaction();
transaction.invoiceID(1);
assert.strictEqual(transaction.tx_json.InvoiceID, void(0));
assert.strictEqual(transaction.tx_json.InvoiceID, undefined);
transaction.invoiceID('DEADBEEF');
assert.strictEqual(transaction.tx_json.InvoiceID, 'DEADBEEF00000000000000000000000000000000000000000000000000000000');
@@ -868,7 +876,7 @@ describe('Transaction', function() {
var transaction = new Transaction();
transaction.clientID(1);
assert.strictEqual(transaction._clientID, void(0));
assert.strictEqual(transaction._clientID, undefined);
transaction.clientID('DEADBEEF');
assert.strictEqual(transaction._clientID, 'DEADBEEF');
@@ -878,11 +886,11 @@ describe('Transaction', function() {
var transaction = new Transaction();
transaction.lastLedger('a');
assert.strictEqual(transaction.tx_json.LastLedgerSequence, void(0));
assert.strictEqual(transaction.tx_json.LastLedgerSequence, undefined);
assert(!transaction._setLastLedger);
transaction.lastLedger(NaN);
assert.strictEqual(transaction.tx_json.LastLedgerSequence, void(0));
assert.strictEqual(transaction.tx_json.LastLedgerSequence, undefined);
assert(!transaction._setLastLedger);
transaction.lastLedger(12);
@@ -922,8 +930,6 @@ describe('Transaction', function() {
});
it('Rewrite transaction path', function() {
var transaction = new Transaction();
var path = [
{
account: 'rP51ycDJw5ZhgvdKiRjBYZKYjsyoCcHmnY',
@@ -965,7 +971,7 @@ describe('Transaction', function() {
it('Rewrite transaction path - invalid path', function() {
assert.throws(function() {
assert.strictEqual(Transaction._rewritePath(1), void(0));
assert.strictEqual(Transaction._rewritePath(1), undefined);
});
});
@@ -974,7 +980,7 @@ describe('Transaction', function() {
transaction.pathAdd(1);
assert.strictEqual(transaction.tx_json.Paths, void(0));
assert.strictEqual(transaction.tx_json.Paths, undefined);
var path = [
{
@@ -1025,7 +1031,7 @@ describe('Transaction', function() {
transaction.paths(1);
assert.strictEqual(transaction.tx_json.Paths, void(0));
assert.strictEqual(transaction.tx_json.Paths, undefined);
transaction.paths([
[{
@@ -1075,7 +1081,7 @@ describe('Transaction', function() {
it('Set SourceTag', function() {
var transaction = new Transaction();
transaction.sourceTag('tag');
assert.strictEqual(transaction.tx_json.SourceTag, void(0));
assert.strictEqual(transaction.tx_json.SourceTag, undefined);
transaction.sourceTag(1);
assert.strictEqual(transaction.tx_json.SourceTag, 1);
});
@@ -1083,7 +1089,7 @@ describe('Transaction', function() {
it('Set TransferRate', function() {
var transaction = new Transaction();
transaction.transferRate(1);
assert.strictEqual(transaction.tx_json.TransferRate, void(0));
assert.strictEqual(transaction.tx_json.TransferRate, undefined);
transaction.transferRate(1.5 * 1e9);
assert.strictEqual(transaction.tx_json.TransferRate, 1.5 * 1e9);
});
@@ -1094,33 +1100,33 @@ describe('Transaction', function() {
transaction.setFlags();
assert.strictEqual(transaction.tx_json.Flags, 0);
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.setFlags(Transaction.flags.Payment.PartialPayment);
assert.strictEqual(transaction.tx_json.Flags, 131072);
var transaction2 = new Transaction();
transaction2.tx_json.TransactionType = 'Payment';
transaction2.setFlags(Transaction.flags.Payment.PartialPayment);
assert.strictEqual(transaction2.tx_json.Flags, 131072);
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.setFlags('NoRippleDirect');
assert.strictEqual(transaction.tx_json.Flags, 65536);
var transaction3 = new Transaction();
transaction3.tx_json.TransactionType = 'Payment';
transaction3.setFlags('NoRippleDirect');
assert.strictEqual(transaction3.tx_json.Flags, 65536);
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.setFlags('PartialPayment', 'NoRippleDirect');
assert.strictEqual(transaction.tx_json.Flags, 196608);
var transaction4 = new Transaction();
transaction4.tx_json.TransactionType = 'Payment';
transaction4.setFlags('PartialPayment', 'NoRippleDirect');
assert.strictEqual(transaction4.tx_json.Flags, 196608);
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.setFlags([ 'LimitQuality', 'PartialPayment' ]);
assert.strictEqual(transaction.tx_json.Flags, 393216);
var transaction5 = new Transaction();
transaction5.tx_json.TransactionType = 'Payment';
transaction5.setFlags(['LimitQuality', 'PartialPayment']);
assert.strictEqual(transaction5.tx_json.Flags, 393216);
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.once('error', function(err) {
var transaction6 = new Transaction();
transaction6.tx_json.TransactionType = 'Payment';
transaction6.once('error', function(err) {
assert.strictEqual(err.result, 'tejInvalidFlag');
done();
});
transaction.setFlags('asdf');
transaction6.setFlags('asdf');
});
it('Add Memo', function() {
@@ -1179,10 +1185,10 @@ describe('Transaction', function() {
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.addMemo('testkey', void(0), 'testvalue');
transaction.addMemo('testkey2', void(0), 'testvalue2');
transaction.addMemo('testkey', undefined, 'testvalue');
transaction.addMemo('testkey2', undefined, 'testvalue2');
transaction.addMemo('testkey3', 'text/html');
transaction.addMemo(void(0), void(0), 'testvalue4');
transaction.addMemo(undefined, undefined, 'testvalue4');
transaction.addMemo('testkey4', 'text/html', '<html>');
var expected = [
@@ -1244,7 +1250,7 @@ describe('Transaction', function() {
transaction.tx_json.TransactionType = 'Payment';
assert.throws(function() {
transaction.addMemo(void(0), 1);
transaction.addMemo(undefined, 1);
}, /^Error: MemoFormat must be a string$/);
});
@@ -1253,7 +1259,7 @@ describe('Transaction', function() {
transaction.tx_json.TransactionType = 'Payment';
assert.throws(function() {
transaction.addMemo(void(0), 'России');
transaction.addMemo(undefined, 'России');
}, /^Error: MemoFormat must be valid ASCII$/);
});
@@ -1261,7 +1267,7 @@ describe('Transaction', function() {
var transaction = new Transaction();
transaction.tx_json.TransactionType = 'Payment';
transaction.addMemo({memoData:'some_string'});
transaction.addMemo({memoData: 'some_string'});
assert.deepEqual(transaction.tx_json.Memos, [
{
@@ -1360,7 +1366,7 @@ describe('Transaction', function() {
it('Construct AccountSet transaction - invalid account', function() {
assert.throws(function() {
var transaction = new Transaction().accountSet('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm');
new Transaction().accountSet('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm');
});
});
@@ -1393,7 +1399,7 @@ describe('Transaction', function() {
it('Construct OfferCancel transaction - invalid account', function() {
assert.throws(function() {
var transaction = new Transaction().offerCancel('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 1);
new Transaction().offerCancel('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', 1);
});
});
@@ -1595,7 +1601,7 @@ describe('Transaction', function() {
it('Construct Payment transaction - invalid account', function() {
assert.throws(function() {
var transaction = new Transaction().payment(
new Transaction().payment(
'xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
'r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe',
'1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'
@@ -1605,7 +1611,7 @@ describe('Transaction', function() {
it('Construct Payment transaction - invalid destination', function() {
assert.throws(function() {
var transaction = new Transaction().payment(
new Transaction().payment(
'rsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm',
'xr36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe',
'1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe'
@@ -1674,7 +1680,7 @@ describe('Transaction', function() {
it('Construct TrustSet transaction - invalid account', function() {
assert.throws(function() {
var limit = '1/USD/r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe';
var transaction = new Transaction().trustSet('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit, 1.0, 1.0);
new Transaction().trustSet('xrsLEU1TPdCJPPysqhWYw9jD97xtG5WqSJm', limit, 1.0, 1.0);
});
});
@@ -1682,9 +1688,9 @@ describe('Transaction', function() {
var remote = new Remote();
var transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe');
assert.strictEqual(transaction.callback, void(0));
assert.strictEqual(transaction._errorHandler, void(0));
assert.strictEqual(transaction._successHandler, void(0));
assert.strictEqual(transaction.callback, undefined);
assert.strictEqual(transaction._errorHandler, undefined);
assert.strictEqual(transaction._successHandler, undefined);
assert.strictEqual(transaction.listeners('error').length, 1);
var account = remote.addAccount('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWe');
@@ -1705,13 +1711,13 @@ describe('Transaction', function() {
receivedSuccess = true;
});
function submitCallback(err, res) {
function submitCallback(err) {
setImmediate(function() {
assert.ifError(err);
assert(receivedSuccess);
done();
});
};
}
transaction.submit(submitCallback);
@@ -1744,14 +1750,14 @@ describe('Transaction', function() {
receivedError = true;
});
function submitCallback(err, res) {
function submitCallback(err) {
setImmediate(function() {
assert(err);
assert.strictEqual(err.constructor.name, 'RippleError');
assert(receivedError);
done();
});
};
}
transaction.submit(submitCallback);
});
@@ -1771,7 +1777,7 @@ describe('Transaction', function() {
it('Submit transaction - invalid account', function(done) {
var remote = new Remote();
assert.throws(function() {
var transaction = new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWeZ');
new Transaction(remote).accountSet('r36xtKNKR43SeXnGn7kN4r4JdQzcrkqpWeZ');
});
done();
});
@@ -1781,7 +1787,9 @@ describe('Transaction', function() {
remote.setSecret('rJaT8TafQfYJqDm8aC5n3Yx5yWEL2Ery79', 'snPwFATthTkKnGjEW73q3TL4yci1Q');
var server = new Server(remote, 'wss://s1.ripple.com:443');
server._computeFee = function() { return '12'; };
server._computeFee = function() {
return '12';
};
server._connected = true;
remote._servers.push(server);
@@ -1797,7 +1805,7 @@ describe('Transaction', function() {
transaction.abort();
});
transaction.submit(function(err, res) {
transaction.submit(function(err) {
setImmediate(function() {
assert(err);
assert.strictEqual(err.result, 'tejAbort');
@@ -1822,7 +1830,7 @@ describe('Transaction', function() {
872298,
543305
]
.forEach(function(index){
.forEach(function(index) {
var tx = new Transaction();
tx.initialSubmitIndex = index;
queue.push(tx);
@@ -1833,11 +1841,9 @@ describe('Transaction', function() {
return a.initialSubmitIndex - b.initialSubmitIndex;
});
sorted.forEach(function(tx){
sorted.forEach(function(tx) {
assert.strictEqual(queue.getMinLedger(), tx.initialSubmitIndex);
queue.remove(tx);
});
});
});
//vim:sw=2:sts=2:ts=8:et