mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
Conflicts: src/SHAMapNodes.cpp
This commit is contained in:
239
js/amount.js
239
js/amount.js
@@ -1,7 +1,10 @@
|
||||
// Represent Newcoin amounts and currencies.
|
||||
// - Numbers in hex are big-endian.
|
||||
|
||||
var utils = require('./utils.js');
|
||||
var jsbn = require('./jsbn.js');
|
||||
|
||||
var utils = require("./utils.js");
|
||||
var BigInteger = jsbn.BigInteger;
|
||||
|
||||
var UInt160 = function () {
|
||||
// Internal form:
|
||||
@@ -9,7 +12,11 @@ var UInt160 = function () {
|
||||
// XXX Should standardize on 'i' format or 20 format.
|
||||
};
|
||||
|
||||
// Returns NaN on error.
|
||||
UInt160.from_json = function (j) {
|
||||
return (new UInt160()).parse_json(j);
|
||||
};
|
||||
|
||||
// value === NaN on error.
|
||||
UInt160.prototype.parse_json = function (j) {
|
||||
// Canonicalize and validate
|
||||
|
||||
@@ -49,7 +56,7 @@ UInt160.prototype.parse_json = function (j) {
|
||||
}
|
||||
}
|
||||
|
||||
return this.value;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Convert from internal form.
|
||||
@@ -62,7 +69,7 @@ UInt160.prototype.to_json = function () {
|
||||
{
|
||||
return exports.consts.hex_one;
|
||||
}
|
||||
else if (20 === this.value.length) {
|
||||
else if ('string' === typeof this.value && 20 === this.value.length) {
|
||||
return utils.stringToHex(this.value);
|
||||
}
|
||||
else
|
||||
@@ -81,7 +88,11 @@ var Currency = function () {
|
||||
// XXX Should support hex, C++ doesn't currently allow it.
|
||||
}
|
||||
|
||||
// Returns NaN on error.
|
||||
Currency.from_json = function (j) {
|
||||
return (new Currency()).parse_json(j);
|
||||
};
|
||||
|
||||
// this.value === NaN on error.
|
||||
Currency.prototype.parse_json = function (j) {
|
||||
if ("" === j || "0" === j || "XNS" === j) {
|
||||
this.value = 0;
|
||||
@@ -93,15 +104,15 @@ Currency.prototype.parse_json = function (j) {
|
||||
this.value = j;
|
||||
}
|
||||
|
||||
return this.value;
|
||||
return this;
|
||||
};
|
||||
|
||||
Currency.prototype.to_json = function () {
|
||||
return this.value ? this.value : 'XNS';
|
||||
return this.value ? this.value : "XNS";
|
||||
};
|
||||
|
||||
Currency.prototype.to_human = function() {
|
||||
return this.value ? this.value : 'XNS';
|
||||
return this.value ? this.value : "XNS";
|
||||
};
|
||||
|
||||
var Amount = function () {
|
||||
@@ -109,19 +120,86 @@ var Amount = function () {
|
||||
// integer : XNS
|
||||
// { 'value' : ..., 'currency' : ..., 'issuer' : ...}
|
||||
|
||||
this.value = 0;
|
||||
this.offset = 0;
|
||||
this.is_native = false;
|
||||
this.is_negative = false;
|
||||
this.value = new BigInteger(); // NaN for bad value. Always positive for non-XNS.
|
||||
this.offset = undefined; // For non-XNS.
|
||||
this.is_native = true; // Default to XNS. Only valid if value is not NaN.
|
||||
this.is_negative = undefined; // Undefined for XNS.
|
||||
|
||||
this.currency = new Currency();
|
||||
this.issuer = new UInt160();
|
||||
};
|
||||
|
||||
// Convert only value to JSON text.
|
||||
Amount.prototype.to_text = function() {
|
||||
// XXX Needs to work for native and non-native.
|
||||
return this.is_negative ? -this.value : this.value; // XXX Use biginteger.
|
||||
Amount.from_json = function (j) {
|
||||
return (new Amount()).parse_json(j);
|
||||
};
|
||||
|
||||
// YYY Might also check range.
|
||||
Amount.prototype.is_valid = function() {
|
||||
return NaN !== this.value;
|
||||
}
|
||||
|
||||
// Convert only value to JSON wire format.
|
||||
Amount.prototype.to_text = function(allow_nan) {
|
||||
if (NaN === this.value) {
|
||||
// Never should happen.
|
||||
return allow_nan ? NaN : "0";
|
||||
}
|
||||
else if (this.is_native) {
|
||||
if (this.value.compareTo(exports.consts.xns_max) > 0 || this.value.compareTo(exports.consts.xns_min) < 0)
|
||||
{
|
||||
// Never should happen.
|
||||
return allow_nan ? NaN : "0";
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.value.toString();
|
||||
}
|
||||
}
|
||||
else if (this.value.equals(BigInteger.ZERO))
|
||||
{
|
||||
return "0";
|
||||
}
|
||||
else if (this.offset < -25 || this.offset > -5)
|
||||
{
|
||||
// Use e notation.
|
||||
// XXX Clamp output.
|
||||
|
||||
return (this.is_negative ? "-" : "") + this.value.toString() + "e" + this.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
var val = "000000000000000000000000000" + this.value.toString() + "00000000000000000000000";
|
||||
var pre = val.substring(0, this.offset + 43);
|
||||
var post = val.substring(this.offset + 43);
|
||||
var s_pre = pre.match(/[1-9].*$/); // Everything but leading zeros.
|
||||
var s_post = post.match(/[1-9]0*$/); // Last non-zero plus trailing zeros.
|
||||
|
||||
return (this.is_negative ? "-" : "")
|
||||
+ (s_pre ? s_pre[0] : "0")
|
||||
+ (s_post ? "." + post.substring(0, 1+post.length-s_post[0].length) : "");
|
||||
}
|
||||
};
|
||||
|
||||
Amount.prototype.canonicalize = function() {
|
||||
if (NaN === this.value || !this.currency) {
|
||||
// nothing
|
||||
}
|
||||
else if (this.value.equals(BigInteger.ZERO)) {
|
||||
this.offset = -100;
|
||||
this.is_negative = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (this.value.compareTo(exports.consts.bi_man_min_value) < 0) {
|
||||
this.value = this.value.multiply(exports.consts.bi_10);
|
||||
this.offset -= 1;
|
||||
}
|
||||
|
||||
while (this.value.compareTo(exports.consts.bi_man_max_value) > 0) {
|
||||
this.value = this.value.divide(exports.consts.bi_10);
|
||||
this.offset += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Amount.prototype.to_json = function() {
|
||||
@@ -138,58 +216,132 @@ Amount.prototype.to_json = function() {
|
||||
}
|
||||
};
|
||||
|
||||
// Parse a native value.
|
||||
Amount.prototype.to_text_full = function() {
|
||||
return this.value === NaN
|
||||
? NaN
|
||||
: this.is_native
|
||||
? this.to_text() + "/XNS"
|
||||
: this.to_text() + "/" + this.currency.to_json() + "/" + this.issuer.to_json();
|
||||
};
|
||||
|
||||
// Parse a XNS value from untrusted input.
|
||||
// - integer = raw units
|
||||
// - float = with precision 6
|
||||
// XXX Improvements: disallow leading zeros.
|
||||
Amount.prototype.parse_native = function(j) {
|
||||
if ('integer' === typeof j) {
|
||||
// XNS
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
var m;
|
||||
|
||||
if ('string' === typeof j)
|
||||
m = j.match(/^(\d+)(\.\d{1,6})?$/);
|
||||
|
||||
if (null !== m) {
|
||||
if (undefined === m[2]) {
|
||||
// Integer notation
|
||||
|
||||
this.value = new BigInteger(m[1]);
|
||||
}
|
||||
else {
|
||||
// Decimal notation
|
||||
|
||||
var int_part = (new BigInteger(m[1])).multiply(exports.consts.xns_unit);
|
||||
var fraction_part = (new BigInteger(m[2])).multiply(new BigInteger(String(Math.pow(10, 1+exports.consts.xns_precision-m[2].length))));
|
||||
|
||||
this.value = int_part.add(fraction_part);
|
||||
}
|
||||
|
||||
this.is_native = true;
|
||||
this.is_negative = j < 0;
|
||||
this.offset = undefined;
|
||||
this.is_negative = undefined;
|
||||
|
||||
if (this.value.compareTo(exports.consts.xns_max) > 0 || this.value.compareTo(exports.consts.xns_min) < 0)
|
||||
{
|
||||
this.value = NaN;
|
||||
}
|
||||
}
|
||||
else if ('string' === typeof j) {
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
this.is_native = true;
|
||||
this.is_negative = j < 0;
|
||||
}
|
||||
else {
|
||||
this.value = NaN;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Parse a non-native value.
|
||||
Amount.prototype.parse_value = function(j) {
|
||||
if ('integer' === typeof j) {
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
if ('number' === typeof j) {
|
||||
this.value = new BigInteger(j);
|
||||
this.offset = 0;
|
||||
this.is_native = false;
|
||||
this.is_negative = j < 0;
|
||||
|
||||
this.canonicalize();
|
||||
}
|
||||
else if ('string' === typeof j) {
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
var e = j.match(/^(-?\d+)e(\d+)/);
|
||||
var d = j.match(/^(-?\d+)\.(\d+)/);
|
||||
|
||||
if (e) {
|
||||
// e notation
|
||||
|
||||
this.value = new BigInteger(e[1]);
|
||||
this.offset = parseInt(e[2]);
|
||||
}
|
||||
else if (d) {
|
||||
// float notation
|
||||
|
||||
var integer = new BigInteger(d[1]);
|
||||
var fraction = new BigInteger(d[2]);
|
||||
this.value = integer.multiply(exports.consts.bi_10.clone().pow(d[2].length)).add(fraction);
|
||||
this.offset = -d[2].length;
|
||||
}
|
||||
else
|
||||
{
|
||||
// integer notation
|
||||
|
||||
this.value = new BigInteger(j);
|
||||
this.offset = 0;
|
||||
}
|
||||
|
||||
this.is_native = false;
|
||||
this.is_negative = j < 0;
|
||||
this.is_negative = undefined;
|
||||
|
||||
this.canonicalize();
|
||||
}
|
||||
else {
|
||||
this.value = NaN;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// <-> j
|
||||
Amount.prototype.parse_json = function(j) {
|
||||
if ('object' === typeof j && j.currency) {
|
||||
if ('string' === typeof j) {
|
||||
// .../.../... notation is not a wire format. But allowed for easier testing.
|
||||
var m = j.match(/^(.+)\/(...)\/(.+)$/);
|
||||
|
||||
this.parse_value(j);
|
||||
if (m) {
|
||||
this.parse_value(m[1]);
|
||||
this.currency = Currency.from_json(m[2]);
|
||||
this.issuer = UInt160.from_json(m[3]);
|
||||
}
|
||||
else {
|
||||
this.parse_native(j);
|
||||
this.currency = new Currency();
|
||||
this.issuer = new UInt160();
|
||||
}
|
||||
}
|
||||
else if ('object' === typeof j && j.currency) {
|
||||
// Never XNS.
|
||||
|
||||
this.parse_value(j.value);
|
||||
this.currency.parse_json(j.currency);
|
||||
this.issuer.parse_json(j.issuer);
|
||||
}
|
||||
else {
|
||||
this.parse_native(j);
|
||||
this.currency = 0;
|
||||
this.issuer = 0;
|
||||
this.value = NaN;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
exports.Amount = Amount;
|
||||
@@ -201,10 +353,17 @@ exports.consts = {
|
||||
'address_one' : "iiiiiiiiiiiiiiiiiiiiBZbvjr",
|
||||
'currency_xns' : 0,
|
||||
'currency_one' : 1,
|
||||
'uint160_xns' : hexToString("0000000000000000000000000000000000000000"),
|
||||
'uint160_one' : hexToString("0000000000000000000000000000000000000001"),
|
||||
'uint160_xns' : utils.hexToString("0000000000000000000000000000000000000000"),
|
||||
'uint160_one' : utils.hexToString("0000000000000000000000000000000000000001"),
|
||||
'hex_xns' : "0000000000000000000000000000000000000000",
|
||||
'hex_one' : "0000000000000000000000000000000000000001",
|
||||
'xns_max' : new BigInteger("9000000000000000000"), // Json wire limit.
|
||||
'xns_min' : new BigInteger("-9000000000000000000"), // Json wire limit.
|
||||
'xns_unit' : new BigInteger('1000000'),
|
||||
'xns_precision' : 6,
|
||||
'bi_man_min_value' : new BigInteger('1000000000000000'),
|
||||
'bi_man_max_value' : new BigInteger('9999999999999999'),
|
||||
'bi_10' : new BigInteger('10'),
|
||||
};
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
|
||||
@@ -1,12 +1,541 @@
|
||||
// Derived from Tom Wu's jsbn code.
|
||||
//
|
||||
// Changes made for clean up and to package as a node.js module.
|
||||
|
||||
// Copyright (c) 2005-2009 Tom Wu
|
||||
// All Rights Reserved.
|
||||
// See "LICENSE" for details.
|
||||
|
||||
// Basic JavaScript BN library - subset useful for RSA encryption.
|
||||
// Extended JavaScript BN functions, required for RSA private ops.
|
||||
|
||||
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
|
||||
// Version 1.2: square() API, isProbablePrime fix
|
||||
|
||||
// Bits per digit
|
||||
var dbits;
|
||||
|
||||
// JavaScript engine analysis
|
||||
var canary = 0xdeadbeefcafe;
|
||||
var j_lm = ((canary&0xffffff)==0xefcafe);
|
||||
|
||||
// (public) Constructor
|
||||
var BigInteger = function BigInteger(a,b,c) {
|
||||
if(a != null)
|
||||
if("number" == typeof a) this.fromNumber(a,b,c);
|
||||
else if(b == null && "string" != typeof a) this.fromString(a,256);
|
||||
else this.fromString(a,b);
|
||||
};
|
||||
|
||||
// return new, unset BigInteger
|
||||
var nbi = function nbi() { return new BigInteger(null); };
|
||||
|
||||
// am: Compute w_j += (x*this_i), propagate carries,
|
||||
// c is initial carry, returns final carry.
|
||||
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
||||
// We need to select the fastest one that works in this environment.
|
||||
|
||||
// am1: use a single mult and divide to get the high bits,
|
||||
// max digit bits should be 26 because
|
||||
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
||||
function am1(i,x,w,j,c,n) {
|
||||
while(--n >= 0) {
|
||||
var v = x*this[i++]+w[j]+c;
|
||||
c = Math.floor(v/0x4000000);
|
||||
w[j++] = v&0x3ffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// am2 avoids a big mult-and-extract completely.
|
||||
// Max digit bits should be <= 30 because we do bitwise ops
|
||||
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
||||
function am2(i,x,w,j,c,n) {
|
||||
var xl = x&0x7fff, xh = x>>15;
|
||||
while(--n >= 0) {
|
||||
var l = this[i]&0x7fff;
|
||||
var h = this[i++]>>15;
|
||||
var m = xh*l+h*xl;
|
||||
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
|
||||
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
|
||||
w[j++] = l&0x3fffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// Alternately, set max digit bits to 28 since some
|
||||
// browsers slow down when dealing with 32-bit numbers.
|
||||
function am3(i,x,w,j,c,n) {
|
||||
var xl = x&0x3fff, xh = x>>14;
|
||||
while(--n >= 0) {
|
||||
var l = this[i]&0x3fff;
|
||||
var h = this[i++]>>14;
|
||||
var m = xh*l+h*xl;
|
||||
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
|
||||
c = (l>>28)+(m>>14)+xh*h;
|
||||
w[j++] = l&0xfffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
if(j_lm && 'undefined' !== typeof navigator && (navigator.appName == "Microsoft Internet Explorer")) {
|
||||
BigInteger.prototype.am = am2;
|
||||
dbits = 30;
|
||||
}
|
||||
else if(j_lm && 'undefined' !== typeof navigator && (navigator.appName != "Netscape")) {
|
||||
BigInteger.prototype.am = am1;
|
||||
dbits = 26;
|
||||
}
|
||||
else { // Mozilla/Netscape seems to prefer am3
|
||||
BigInteger.prototype.am = am3;
|
||||
dbits = 28;
|
||||
}
|
||||
|
||||
BigInteger.prototype.DB = dbits;
|
||||
BigInteger.prototype.DM = ((1<<dbits)-1);
|
||||
BigInteger.prototype.DV = (1<<dbits);
|
||||
|
||||
var BI_FP = 52;
|
||||
BigInteger.prototype.FV = Math.pow(2,BI_FP);
|
||||
BigInteger.prototype.F1 = BI_FP-dbits;
|
||||
BigInteger.prototype.F2 = 2*dbits-BI_FP;
|
||||
|
||||
// Digit conversions
|
||||
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
var BI_RC = new Array();
|
||||
var rr,vv;
|
||||
rr = "0".charCodeAt(0);
|
||||
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
|
||||
rr = "a".charCodeAt(0);
|
||||
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||
rr = "A".charCodeAt(0);
|
||||
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||
|
||||
function int2char(n) { return BI_RM.charAt(n); }
|
||||
function intAt(s,i) {
|
||||
var c = BI_RC[s.charCodeAt(i)];
|
||||
return (c==null)?-1:c;
|
||||
}
|
||||
|
||||
// (protected) copy this to r
|
||||
function bnpCopyTo(r) {
|
||||
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
|
||||
r.t = this.t;
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) set from integer value x, -DV <= x < DV
|
||||
function bnpFromInt(x) {
|
||||
this.t = 1;
|
||||
this.s = (x<0)?-1:0;
|
||||
if(x > 0) this[0] = x;
|
||||
else if(x < -1) this[0] = x+DV;
|
||||
else this.t = 0;
|
||||
}
|
||||
|
||||
// return bigint initialized to value
|
||||
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
|
||||
|
||||
// (protected) set from string and radix
|
||||
function bnpFromString(s,b) {
|
||||
var k;
|
||||
if(b == 16) k = 4;
|
||||
else if(b == 8) k = 3;
|
||||
else if(b == 256) k = 8; // byte array
|
||||
else if(b == 2) k = 1;
|
||||
else if(b == 32) k = 5;
|
||||
else if(b == 4) k = 2;
|
||||
else { this.fromRadix(s,b); return; }
|
||||
this.t = 0;
|
||||
this.s = 0;
|
||||
var i = s.length, mi = false, sh = 0;
|
||||
while(--i >= 0) {
|
||||
var x = (k==8)?s[i]&0xff:intAt(s,i);
|
||||
if(x < 0) {
|
||||
if(s.charAt(i) == "-") mi = true;
|
||||
continue;
|
||||
}
|
||||
mi = false;
|
||||
if(sh == 0)
|
||||
this[this.t++] = x;
|
||||
else if(sh+k > this.DB) {
|
||||
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
|
||||
this[this.t++] = (x>>(this.DB-sh));
|
||||
}
|
||||
else
|
||||
this[this.t-1] |= x<<sh;
|
||||
sh += k;
|
||||
if(sh >= this.DB) sh -= this.DB;
|
||||
}
|
||||
if(k == 8 && (s[0]&0x80) != 0) {
|
||||
this.s = -1;
|
||||
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
|
||||
}
|
||||
this.clamp();
|
||||
if(mi) BigInteger.ZERO.subTo(this,this);
|
||||
}
|
||||
|
||||
// (protected) clamp off excess high words
|
||||
function bnpClamp() {
|
||||
var c = this.s&this.DM;
|
||||
while(this.t > 0 && this[this.t-1] == c) --this.t;
|
||||
}
|
||||
|
||||
// (public) return string representation in given radix
|
||||
function bnToString(b) {
|
||||
if(this.s < 0) return "-"+this.negate().toString(b);
|
||||
var k;
|
||||
if(b == 16) k = 4;
|
||||
else if(b == 8) k = 3;
|
||||
else if(b == 2) k = 1;
|
||||
else if(b == 32) k = 5;
|
||||
else if(b == 4) k = 2;
|
||||
else return this.toRadix(b);
|
||||
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
|
||||
var p = this.DB-(i*this.DB)%k;
|
||||
if(i-- > 0) {
|
||||
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
|
||||
while(i >= 0) {
|
||||
if(p < k) {
|
||||
d = (this[i]&((1<<p)-1))<<(k-p);
|
||||
d |= this[--i]>>(p+=this.DB-k);
|
||||
}
|
||||
else {
|
||||
d = (this[i]>>(p-=k))&km;
|
||||
if(p <= 0) { p += this.DB; --i; }
|
||||
}
|
||||
if(d > 0) m = true;
|
||||
if(m) r += int2char(d);
|
||||
}
|
||||
}
|
||||
return m?r:"0";
|
||||
}
|
||||
|
||||
// (public) -this
|
||||
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
|
||||
|
||||
// (public) |this|
|
||||
function bnAbs() { return (this.s<0)?this.negate():this; }
|
||||
|
||||
// (public) return + if this > a, - if this < a, 0 if equal
|
||||
function bnCompareTo(a) {
|
||||
var r = this.s-a.s;
|
||||
if(r != 0) return r;
|
||||
var i = this.t;
|
||||
r = i-a.t;
|
||||
if(r != 0) return (this.s<0)?-r:r;
|
||||
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns bit length of the integer x
|
||||
function nbits(x) {
|
||||
var r = 1, t;
|
||||
if((t=x>>>16) != 0) { x = t; r += 16; }
|
||||
if((t=x>>8) != 0) { x = t; r += 8; }
|
||||
if((t=x>>4) != 0) { x = t; r += 4; }
|
||||
if((t=x>>2) != 0) { x = t; r += 2; }
|
||||
if((t=x>>1) != 0) { x = t; r += 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) return the number of bits in "this"
|
||||
function bnBitLength() {
|
||||
if(this.t <= 0) return 0;
|
||||
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
|
||||
}
|
||||
|
||||
// (protected) r = this << n*DB
|
||||
function bnpDLShiftTo(n,r) {
|
||||
var i;
|
||||
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
|
||||
for(i = n-1; i >= 0; --i) r[i] = 0;
|
||||
r.t = this.t+n;
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) r = this >> n*DB
|
||||
function bnpDRShiftTo(n,r) {
|
||||
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
|
||||
r.t = Math.max(this.t-n,0);
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) r = this << n
|
||||
function bnpLShiftTo(n,r) {
|
||||
var bs = n%this.DB;
|
||||
var cbs = this.DB-bs;
|
||||
var bm = (1<<cbs)-1;
|
||||
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
|
||||
for(i = this.t-1; i >= 0; --i) {
|
||||
r[i+ds+1] = (this[i]>>cbs)|c;
|
||||
c = (this[i]&bm)<<bs;
|
||||
}
|
||||
for(i = ds-1; i >= 0; --i) r[i] = 0;
|
||||
r[ds] = c;
|
||||
r.t = this.t+ds+1;
|
||||
r.s = this.s;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this >> n
|
||||
function bnpRShiftTo(n,r) {
|
||||
r.s = this.s;
|
||||
var ds = Math.floor(n/this.DB);
|
||||
if(ds >= this.t) { r.t = 0; return; }
|
||||
var bs = n%this.DB;
|
||||
var cbs = this.DB-bs;
|
||||
var bm = (1<<bs)-1;
|
||||
r[0] = this[ds]>>bs;
|
||||
for(var i = ds+1; i < this.t; ++i) {
|
||||
r[i-ds-1] |= (this[i]&bm)<<cbs;
|
||||
r[i-ds] = this[i]>>bs;
|
||||
}
|
||||
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
|
||||
r.t = this.t-ds;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this - a
|
||||
function bnpSubTo(a,r) {
|
||||
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
||||
while(i < m) {
|
||||
c += this[i]-a[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
if(a.t < this.t) {
|
||||
c -= a.s;
|
||||
while(i < this.t) {
|
||||
c += this[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
c += this.s;
|
||||
}
|
||||
else {
|
||||
c += this.s;
|
||||
while(i < a.t) {
|
||||
c -= a[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
c -= a.s;
|
||||
}
|
||||
r.s = (c<0)?-1:0;
|
||||
if(c < -1) r[i++] = this.DV+c;
|
||||
else if(c > 0) r[i++] = c;
|
||||
r.t = i;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this * a, r != this,a (HAC 14.12)
|
||||
// "this" should be the larger one if appropriate.
|
||||
function bnpMultiplyTo(a,r) {
|
||||
var x = this.abs(), y = a.abs();
|
||||
var i = x.t;
|
||||
r.t = i+y.t;
|
||||
while(--i >= 0) r[i] = 0;
|
||||
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
|
||||
r.s = 0;
|
||||
r.clamp();
|
||||
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
|
||||
}
|
||||
|
||||
// (protected) r = this^2, r != this (HAC 14.16)
|
||||
function bnpSquareTo(r) {
|
||||
var x = this.abs();
|
||||
var i = r.t = 2*x.t;
|
||||
while(--i >= 0) r[i] = 0;
|
||||
for(i = 0; i < x.t-1; ++i) {
|
||||
var c = x.am(i,x[i],r,2*i,0,1);
|
||||
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
|
||||
r[i+x.t] -= x.DV;
|
||||
r[i+x.t+1] = 1;
|
||||
}
|
||||
}
|
||||
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
|
||||
r.s = 0;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
||||
// r != q, this != m. q or r may be null.
|
||||
function bnpDivRemTo(m,q,r) {
|
||||
var pm = m.abs();
|
||||
if(pm.t <= 0) return;
|
||||
var pt = this.abs();
|
||||
if(pt.t < pm.t) {
|
||||
if(q != null) q.fromInt(0);
|
||||
if(r != null) this.copyTo(r);
|
||||
return;
|
||||
}
|
||||
if(r == null) r = nbi();
|
||||
var y = nbi(), ts = this.s, ms = m.s;
|
||||
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
|
||||
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
|
||||
else { pm.copyTo(y); pt.copyTo(r); }
|
||||
var ys = y.t;
|
||||
var y0 = y[ys-1];
|
||||
if(y0 == 0) return;
|
||||
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
|
||||
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
|
||||
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
|
||||
y.dlShiftTo(j,t);
|
||||
if(r.compareTo(t) >= 0) {
|
||||
r[r.t++] = 1;
|
||||
r.subTo(t,r);
|
||||
}
|
||||
BigInteger.ONE.dlShiftTo(ys,t);
|
||||
t.subTo(y,y); // "negative" y so we can replace sub with am later
|
||||
while(y.t < ys) y[y.t++] = 0;
|
||||
while(--j >= 0) {
|
||||
// Estimate quotient digit
|
||||
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
|
||||
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
|
||||
y.dlShiftTo(j,t);
|
||||
r.subTo(t,r);
|
||||
while(r[i] < --qd) r.subTo(t,r);
|
||||
}
|
||||
}
|
||||
if(q != null) {
|
||||
r.drShiftTo(ys,q);
|
||||
if(ts != ms) BigInteger.ZERO.subTo(q,q);
|
||||
}
|
||||
r.t = ys;
|
||||
r.clamp();
|
||||
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
|
||||
if(ts < 0) BigInteger.ZERO.subTo(r,r);
|
||||
}
|
||||
|
||||
// (public) this mod a
|
||||
function bnMod(a) {
|
||||
var r = nbi();
|
||||
this.abs().divRemTo(a,null,r);
|
||||
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Modular reduction using "classic" algorithm
|
||||
function Classic(m) { this.m = m; }
|
||||
function cConvert(x) {
|
||||
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
|
||||
else return x;
|
||||
}
|
||||
function cRevert(x) { return x; }
|
||||
function cReduce(x) { x.divRemTo(this.m,null,x); }
|
||||
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||
|
||||
Classic.prototype.convert = cConvert;
|
||||
Classic.prototype.revert = cRevert;
|
||||
Classic.prototype.reduce = cReduce;
|
||||
Classic.prototype.mulTo = cMulTo;
|
||||
Classic.prototype.sqrTo = cSqrTo;
|
||||
|
||||
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
||||
// justification:
|
||||
// xy == 1 (mod m)
|
||||
// xy = 1+km
|
||||
// xy(2-xy) = (1+km)(1-km)
|
||||
// x[y(2-xy)] = 1-k^2m^2
|
||||
// x[y(2-xy)] == 1 (mod m^2)
|
||||
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
||||
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
||||
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
||||
function bnpInvDigit() {
|
||||
if(this.t < 1) return 0;
|
||||
var x = this[0];
|
||||
if((x&1) == 0) return 0;
|
||||
var y = x&3; // y == 1/x mod 2^2
|
||||
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
|
||||
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
|
||||
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
|
||||
// last step - calculate inverse mod DV directly;
|
||||
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
||||
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
|
||||
// we really want the negative inverse, and -DV < y < DV
|
||||
return (y>0)?this.DV-y:-y;
|
||||
}
|
||||
|
||||
// Montgomery reduction
|
||||
function Montgomery(m) {
|
||||
this.m = m;
|
||||
this.mp = m.invDigit();
|
||||
this.mpl = this.mp&0x7fff;
|
||||
this.mph = this.mp>>15;
|
||||
this.um = (1<<(m.DB-15))-1;
|
||||
this.mt2 = 2*m.t;
|
||||
}
|
||||
|
||||
// xR mod m
|
||||
function montConvert(x) {
|
||||
var r = nbi();
|
||||
x.abs().dlShiftTo(this.m.t,r);
|
||||
r.divRemTo(this.m,null,r);
|
||||
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// x/R mod m
|
||||
function montRevert(x) {
|
||||
var r = nbi();
|
||||
x.copyTo(r);
|
||||
this.reduce(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// x = x/R mod m (HAC 14.32)
|
||||
function montReduce(x) {
|
||||
while(x.t <= this.mt2) // pad x so am has enough room later
|
||||
x[x.t++] = 0;
|
||||
for(var i = 0; i < this.m.t; ++i) {
|
||||
// faster way of calculating u0 = x[i]*mp mod DV
|
||||
var j = x[i]&0x7fff;
|
||||
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
|
||||
// use am to combine the multiply-shift-add into one call
|
||||
j = i+this.m.t;
|
||||
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
|
||||
// propagate carry
|
||||
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
|
||||
}
|
||||
x.clamp();
|
||||
x.drShiftTo(this.m.t,x);
|
||||
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
||||
}
|
||||
|
||||
// r = "x^2/R mod m"; x != r
|
||||
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||
|
||||
// r = "xy/R mod m"; x,y != r
|
||||
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||
|
||||
Montgomery.prototype.convert = montConvert;
|
||||
Montgomery.prototype.revert = montRevert;
|
||||
Montgomery.prototype.reduce = montReduce;
|
||||
Montgomery.prototype.mulTo = montMulTo;
|
||||
Montgomery.prototype.sqrTo = montSqrTo;
|
||||
|
||||
// (protected) true iff this is even
|
||||
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
|
||||
|
||||
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
||||
function bnpExp(e,z) {
|
||||
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
|
||||
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
|
||||
g.copyTo(r);
|
||||
while(--i >= 0) {
|
||||
z.sqrTo(r,r2);
|
||||
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
|
||||
else { var t = r; r = r2; r2 = t; }
|
||||
}
|
||||
return z.revert(r);
|
||||
}
|
||||
|
||||
// (public) this^e % m, 0 <= e < 2^32
|
||||
function bnModPowInt(e,m) {
|
||||
var z;
|
||||
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
|
||||
return this.exp(e,z);
|
||||
}
|
||||
|
||||
// (public)
|
||||
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
|
||||
|
||||
@@ -654,3 +1183,37 @@ BigInteger.prototype.square = bnSquare;
|
||||
// int hashCode()
|
||||
// long longValue()
|
||||
// static BigInteger valueOf(long val)
|
||||
// protected
|
||||
BigInteger.prototype.copyTo = bnpCopyTo;
|
||||
BigInteger.prototype.fromInt = bnpFromInt;
|
||||
BigInteger.prototype.fromString = bnpFromString;
|
||||
BigInteger.prototype.clamp = bnpClamp;
|
||||
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
|
||||
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
|
||||
BigInteger.prototype.lShiftTo = bnpLShiftTo;
|
||||
BigInteger.prototype.rShiftTo = bnpRShiftTo;
|
||||
BigInteger.prototype.subTo = bnpSubTo;
|
||||
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
|
||||
BigInteger.prototype.squareTo = bnpSquareTo;
|
||||
BigInteger.prototype.divRemTo = bnpDivRemTo;
|
||||
BigInteger.prototype.invDigit = bnpInvDigit;
|
||||
BigInteger.prototype.isEven = bnpIsEven;
|
||||
BigInteger.prototype.exp = bnpExp;
|
||||
|
||||
// public
|
||||
BigInteger.prototype.toString = bnToString;
|
||||
BigInteger.prototype.negate = bnNegate;
|
||||
BigInteger.prototype.abs = bnAbs;
|
||||
BigInteger.prototype.compareTo = bnCompareTo;
|
||||
BigInteger.prototype.bitLength = bnBitLength;
|
||||
BigInteger.prototype.mod = bnMod;
|
||||
BigInteger.prototype.modPowInt = bnModPowInt;
|
||||
|
||||
// "constants"
|
||||
BigInteger.ZERO = nbv(0);
|
||||
BigInteger.ONE = nbv(1);
|
||||
|
||||
exports.nbi = nbi;
|
||||
exports.BigInteger = BigInteger;
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
559
js/jsbn/jsbn.js
559
js/jsbn/jsbn.js
@@ -1,559 +0,0 @@
|
||||
// Copyright (c) 2005 Tom Wu
|
||||
// All Rights Reserved.
|
||||
// See "LICENSE" for details.
|
||||
|
||||
// Basic JavaScript BN library - subset useful for RSA encryption.
|
||||
|
||||
// Bits per digit
|
||||
var dbits;
|
||||
|
||||
// JavaScript engine analysis
|
||||
var canary = 0xdeadbeefcafe;
|
||||
var j_lm = ((canary&0xffffff)==0xefcafe);
|
||||
|
||||
// (public) Constructor
|
||||
function BigInteger(a,b,c) {
|
||||
if(a != null)
|
||||
if("number" == typeof a) this.fromNumber(a,b,c);
|
||||
else if(b == null && "string" != typeof a) this.fromString(a,256);
|
||||
else this.fromString(a,b);
|
||||
}
|
||||
|
||||
// return new, unset BigInteger
|
||||
function nbi() { return new BigInteger(null); }
|
||||
|
||||
// am: Compute w_j += (x*this_i), propagate carries,
|
||||
// c is initial carry, returns final carry.
|
||||
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
||||
// We need to select the fastest one that works in this environment.
|
||||
|
||||
// am1: use a single mult and divide to get the high bits,
|
||||
// max digit bits should be 26 because
|
||||
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
||||
function am1(i,x,w,j,c,n) {
|
||||
while(--n >= 0) {
|
||||
var v = x*this[i++]+w[j]+c;
|
||||
c = Math.floor(v/0x4000000);
|
||||
w[j++] = v&0x3ffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// am2 avoids a big mult-and-extract completely.
|
||||
// Max digit bits should be <= 30 because we do bitwise ops
|
||||
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
||||
function am2(i,x,w,j,c,n) {
|
||||
var xl = x&0x7fff, xh = x>>15;
|
||||
while(--n >= 0) {
|
||||
var l = this[i]&0x7fff;
|
||||
var h = this[i++]>>15;
|
||||
var m = xh*l+h*xl;
|
||||
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
|
||||
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
|
||||
w[j++] = l&0x3fffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
// Alternately, set max digit bits to 28 since some
|
||||
// browsers slow down when dealing with 32-bit numbers.
|
||||
function am3(i,x,w,j,c,n) {
|
||||
var xl = x&0x3fff, xh = x>>14;
|
||||
while(--n >= 0) {
|
||||
var l = this[i]&0x3fff;
|
||||
var h = this[i++]>>14;
|
||||
var m = xh*l+h*xl;
|
||||
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
|
||||
c = (l>>28)+(m>>14)+xh*h;
|
||||
w[j++] = l&0xfffffff;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
|
||||
BigInteger.prototype.am = am2;
|
||||
dbits = 30;
|
||||
}
|
||||
else if(j_lm && (navigator.appName != "Netscape")) {
|
||||
BigInteger.prototype.am = am1;
|
||||
dbits = 26;
|
||||
}
|
||||
else { // Mozilla/Netscape seems to prefer am3
|
||||
BigInteger.prototype.am = am3;
|
||||
dbits = 28;
|
||||
}
|
||||
|
||||
BigInteger.prototype.DB = dbits;
|
||||
BigInteger.prototype.DM = ((1<<dbits)-1);
|
||||
BigInteger.prototype.DV = (1<<dbits);
|
||||
|
||||
var BI_FP = 52;
|
||||
BigInteger.prototype.FV = Math.pow(2,BI_FP);
|
||||
BigInteger.prototype.F1 = BI_FP-dbits;
|
||||
BigInteger.prototype.F2 = 2*dbits-BI_FP;
|
||||
|
||||
// Digit conversions
|
||||
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
var BI_RC = new Array();
|
||||
var rr,vv;
|
||||
rr = "0".charCodeAt(0);
|
||||
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
|
||||
rr = "a".charCodeAt(0);
|
||||
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||
rr = "A".charCodeAt(0);
|
||||
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||||
|
||||
function int2char(n) { return BI_RM.charAt(n); }
|
||||
function intAt(s,i) {
|
||||
var c = BI_RC[s.charCodeAt(i)];
|
||||
return (c==null)?-1:c;
|
||||
}
|
||||
|
||||
// (protected) copy this to r
|
||||
function bnpCopyTo(r) {
|
||||
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
|
||||
r.t = this.t;
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) set from integer value x, -DV <= x < DV
|
||||
function bnpFromInt(x) {
|
||||
this.t = 1;
|
||||
this.s = (x<0)?-1:0;
|
||||
if(x > 0) this[0] = x;
|
||||
else if(x < -1) this[0] = x+DV;
|
||||
else this.t = 0;
|
||||
}
|
||||
|
||||
// return bigint initialized to value
|
||||
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
|
||||
|
||||
// (protected) set from string and radix
|
||||
function bnpFromString(s,b) {
|
||||
var k;
|
||||
if(b == 16) k = 4;
|
||||
else if(b == 8) k = 3;
|
||||
else if(b == 256) k = 8; // byte array
|
||||
else if(b == 2) k = 1;
|
||||
else if(b == 32) k = 5;
|
||||
else if(b == 4) k = 2;
|
||||
else { this.fromRadix(s,b); return; }
|
||||
this.t = 0;
|
||||
this.s = 0;
|
||||
var i = s.length, mi = false, sh = 0;
|
||||
while(--i >= 0) {
|
||||
var x = (k==8)?s[i]&0xff:intAt(s,i);
|
||||
if(x < 0) {
|
||||
if(s.charAt(i) == "-") mi = true;
|
||||
continue;
|
||||
}
|
||||
mi = false;
|
||||
if(sh == 0)
|
||||
this[this.t++] = x;
|
||||
else if(sh+k > this.DB) {
|
||||
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
|
||||
this[this.t++] = (x>>(this.DB-sh));
|
||||
}
|
||||
else
|
||||
this[this.t-1] |= x<<sh;
|
||||
sh += k;
|
||||
if(sh >= this.DB) sh -= this.DB;
|
||||
}
|
||||
if(k == 8 && (s[0]&0x80) != 0) {
|
||||
this.s = -1;
|
||||
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
|
||||
}
|
||||
this.clamp();
|
||||
if(mi) BigInteger.ZERO.subTo(this,this);
|
||||
}
|
||||
|
||||
// (protected) clamp off excess high words
|
||||
function bnpClamp() {
|
||||
var c = this.s&this.DM;
|
||||
while(this.t > 0 && this[this.t-1] == c) --this.t;
|
||||
}
|
||||
|
||||
// (public) return string representation in given radix
|
||||
function bnToString(b) {
|
||||
if(this.s < 0) return "-"+this.negate().toString(b);
|
||||
var k;
|
||||
if(b == 16) k = 4;
|
||||
else if(b == 8) k = 3;
|
||||
else if(b == 2) k = 1;
|
||||
else if(b == 32) k = 5;
|
||||
else if(b == 4) k = 2;
|
||||
else return this.toRadix(b);
|
||||
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
|
||||
var p = this.DB-(i*this.DB)%k;
|
||||
if(i-- > 0) {
|
||||
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
|
||||
while(i >= 0) {
|
||||
if(p < k) {
|
||||
d = (this[i]&((1<<p)-1))<<(k-p);
|
||||
d |= this[--i]>>(p+=this.DB-k);
|
||||
}
|
||||
else {
|
||||
d = (this[i]>>(p-=k))&km;
|
||||
if(p <= 0) { p += this.DB; --i; }
|
||||
}
|
||||
if(d > 0) m = true;
|
||||
if(m) r += int2char(d);
|
||||
}
|
||||
}
|
||||
return m?r:"0";
|
||||
}
|
||||
|
||||
// (public) -this
|
||||
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
|
||||
|
||||
// (public) |this|
|
||||
function bnAbs() { return (this.s<0)?this.negate():this; }
|
||||
|
||||
// (public) return + if this > a, - if this < a, 0 if equal
|
||||
function bnCompareTo(a) {
|
||||
var r = this.s-a.s;
|
||||
if(r != 0) return r;
|
||||
var i = this.t;
|
||||
r = i-a.t;
|
||||
if(r != 0) return (this.s<0)?-r:r;
|
||||
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns bit length of the integer x
|
||||
function nbits(x) {
|
||||
var r = 1, t;
|
||||
if((t=x>>>16) != 0) { x = t; r += 16; }
|
||||
if((t=x>>8) != 0) { x = t; r += 8; }
|
||||
if((t=x>>4) != 0) { x = t; r += 4; }
|
||||
if((t=x>>2) != 0) { x = t; r += 2; }
|
||||
if((t=x>>1) != 0) { x = t; r += 1; }
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) return the number of bits in "this"
|
||||
function bnBitLength() {
|
||||
if(this.t <= 0) return 0;
|
||||
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
|
||||
}
|
||||
|
||||
// (protected) r = this << n*DB
|
||||
function bnpDLShiftTo(n,r) {
|
||||
var i;
|
||||
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
|
||||
for(i = n-1; i >= 0; --i) r[i] = 0;
|
||||
r.t = this.t+n;
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) r = this >> n*DB
|
||||
function bnpDRShiftTo(n,r) {
|
||||
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
|
||||
r.t = Math.max(this.t-n,0);
|
||||
r.s = this.s;
|
||||
}
|
||||
|
||||
// (protected) r = this << n
|
||||
function bnpLShiftTo(n,r) {
|
||||
var bs = n%this.DB;
|
||||
var cbs = this.DB-bs;
|
||||
var bm = (1<<cbs)-1;
|
||||
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
|
||||
for(i = this.t-1; i >= 0; --i) {
|
||||
r[i+ds+1] = (this[i]>>cbs)|c;
|
||||
c = (this[i]&bm)<<bs;
|
||||
}
|
||||
for(i = ds-1; i >= 0; --i) r[i] = 0;
|
||||
r[ds] = c;
|
||||
r.t = this.t+ds+1;
|
||||
r.s = this.s;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this >> n
|
||||
function bnpRShiftTo(n,r) {
|
||||
r.s = this.s;
|
||||
var ds = Math.floor(n/this.DB);
|
||||
if(ds >= this.t) { r.t = 0; return; }
|
||||
var bs = n%this.DB;
|
||||
var cbs = this.DB-bs;
|
||||
var bm = (1<<bs)-1;
|
||||
r[0] = this[ds]>>bs;
|
||||
for(var i = ds+1; i < this.t; ++i) {
|
||||
r[i-ds-1] |= (this[i]&bm)<<cbs;
|
||||
r[i-ds] = this[i]>>bs;
|
||||
}
|
||||
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
|
||||
r.t = this.t-ds;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this - a
|
||||
function bnpSubTo(a,r) {
|
||||
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
||||
while(i < m) {
|
||||
c += this[i]-a[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
if(a.t < this.t) {
|
||||
c -= a.s;
|
||||
while(i < this.t) {
|
||||
c += this[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
c += this.s;
|
||||
}
|
||||
else {
|
||||
c += this.s;
|
||||
while(i < a.t) {
|
||||
c -= a[i];
|
||||
r[i++] = c&this.DM;
|
||||
c >>= this.DB;
|
||||
}
|
||||
c -= a.s;
|
||||
}
|
||||
r.s = (c<0)?-1:0;
|
||||
if(c < -1) r[i++] = this.DV+c;
|
||||
else if(c > 0) r[i++] = c;
|
||||
r.t = i;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = this * a, r != this,a (HAC 14.12)
|
||||
// "this" should be the larger one if appropriate.
|
||||
function bnpMultiplyTo(a,r) {
|
||||
var x = this.abs(), y = a.abs();
|
||||
var i = x.t;
|
||||
r.t = i+y.t;
|
||||
while(--i >= 0) r[i] = 0;
|
||||
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
|
||||
r.s = 0;
|
||||
r.clamp();
|
||||
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
|
||||
}
|
||||
|
||||
// (protected) r = this^2, r != this (HAC 14.16)
|
||||
function bnpSquareTo(r) {
|
||||
var x = this.abs();
|
||||
var i = r.t = 2*x.t;
|
||||
while(--i >= 0) r[i] = 0;
|
||||
for(i = 0; i < x.t-1; ++i) {
|
||||
var c = x.am(i,x[i],r,2*i,0,1);
|
||||
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
|
||||
r[i+x.t] -= x.DV;
|
||||
r[i+x.t+1] = 1;
|
||||
}
|
||||
}
|
||||
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
|
||||
r.s = 0;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
||||
// r != q, this != m. q or r may be null.
|
||||
function bnpDivRemTo(m,q,r) {
|
||||
var pm = m.abs();
|
||||
if(pm.t <= 0) return;
|
||||
var pt = this.abs();
|
||||
if(pt.t < pm.t) {
|
||||
if(q != null) q.fromInt(0);
|
||||
if(r != null) this.copyTo(r);
|
||||
return;
|
||||
}
|
||||
if(r == null) r = nbi();
|
||||
var y = nbi(), ts = this.s, ms = m.s;
|
||||
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
|
||||
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
|
||||
else { pm.copyTo(y); pt.copyTo(r); }
|
||||
var ys = y.t;
|
||||
var y0 = y[ys-1];
|
||||
if(y0 == 0) return;
|
||||
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
|
||||
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
|
||||
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
|
||||
y.dlShiftTo(j,t);
|
||||
if(r.compareTo(t) >= 0) {
|
||||
r[r.t++] = 1;
|
||||
r.subTo(t,r);
|
||||
}
|
||||
BigInteger.ONE.dlShiftTo(ys,t);
|
||||
t.subTo(y,y); // "negative" y so we can replace sub with am later
|
||||
while(y.t < ys) y[y.t++] = 0;
|
||||
while(--j >= 0) {
|
||||
// Estimate quotient digit
|
||||
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
|
||||
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
|
||||
y.dlShiftTo(j,t);
|
||||
r.subTo(t,r);
|
||||
while(r[i] < --qd) r.subTo(t,r);
|
||||
}
|
||||
}
|
||||
if(q != null) {
|
||||
r.drShiftTo(ys,q);
|
||||
if(ts != ms) BigInteger.ZERO.subTo(q,q);
|
||||
}
|
||||
r.t = ys;
|
||||
r.clamp();
|
||||
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
|
||||
if(ts < 0) BigInteger.ZERO.subTo(r,r);
|
||||
}
|
||||
|
||||
// (public) this mod a
|
||||
function bnMod(a) {
|
||||
var r = nbi();
|
||||
this.abs().divRemTo(a,null,r);
|
||||
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Modular reduction using "classic" algorithm
|
||||
function Classic(m) { this.m = m; }
|
||||
function cConvert(x) {
|
||||
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
|
||||
else return x;
|
||||
}
|
||||
function cRevert(x) { return x; }
|
||||
function cReduce(x) { x.divRemTo(this.m,null,x); }
|
||||
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||
|
||||
Classic.prototype.convert = cConvert;
|
||||
Classic.prototype.revert = cRevert;
|
||||
Classic.prototype.reduce = cReduce;
|
||||
Classic.prototype.mulTo = cMulTo;
|
||||
Classic.prototype.sqrTo = cSqrTo;
|
||||
|
||||
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
||||
// justification:
|
||||
// xy == 1 (mod m)
|
||||
// xy = 1+km
|
||||
// xy(2-xy) = (1+km)(1-km)
|
||||
// x[y(2-xy)] = 1-k^2m^2
|
||||
// x[y(2-xy)] == 1 (mod m^2)
|
||||
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
||||
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
||||
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
||||
function bnpInvDigit() {
|
||||
if(this.t < 1) return 0;
|
||||
var x = this[0];
|
||||
if((x&1) == 0) return 0;
|
||||
var y = x&3; // y == 1/x mod 2^2
|
||||
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
|
||||
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
|
||||
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
|
||||
// last step - calculate inverse mod DV directly;
|
||||
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
||||
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
|
||||
// we really want the negative inverse, and -DV < y < DV
|
||||
return (y>0)?this.DV-y:-y;
|
||||
}
|
||||
|
||||
// Montgomery reduction
|
||||
function Montgomery(m) {
|
||||
this.m = m;
|
||||
this.mp = m.invDigit();
|
||||
this.mpl = this.mp&0x7fff;
|
||||
this.mph = this.mp>>15;
|
||||
this.um = (1<<(m.DB-15))-1;
|
||||
this.mt2 = 2*m.t;
|
||||
}
|
||||
|
||||
// xR mod m
|
||||
function montConvert(x) {
|
||||
var r = nbi();
|
||||
x.abs().dlShiftTo(this.m.t,r);
|
||||
r.divRemTo(this.m,null,r);
|
||||
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// x/R mod m
|
||||
function montRevert(x) {
|
||||
var r = nbi();
|
||||
x.copyTo(r);
|
||||
this.reduce(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// x = x/R mod m (HAC 14.32)
|
||||
function montReduce(x) {
|
||||
while(x.t <= this.mt2) // pad x so am has enough room later
|
||||
x[x.t++] = 0;
|
||||
for(var i = 0; i < this.m.t; ++i) {
|
||||
// faster way of calculating u0 = x[i]*mp mod DV
|
||||
var j = x[i]&0x7fff;
|
||||
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
|
||||
// use am to combine the multiply-shift-add into one call
|
||||
j = i+this.m.t;
|
||||
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
|
||||
// propagate carry
|
||||
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
|
||||
}
|
||||
x.clamp();
|
||||
x.drShiftTo(this.m.t,x);
|
||||
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
||||
}
|
||||
|
||||
// r = "x^2/R mod m"; x != r
|
||||
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||
|
||||
// r = "xy/R mod m"; x,y != r
|
||||
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||
|
||||
Montgomery.prototype.convert = montConvert;
|
||||
Montgomery.prototype.revert = montRevert;
|
||||
Montgomery.prototype.reduce = montReduce;
|
||||
Montgomery.prototype.mulTo = montMulTo;
|
||||
Montgomery.prototype.sqrTo = montSqrTo;
|
||||
|
||||
// (protected) true iff this is even
|
||||
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
|
||||
|
||||
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
||||
function bnpExp(e,z) {
|
||||
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
|
||||
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
|
||||
g.copyTo(r);
|
||||
while(--i >= 0) {
|
||||
z.sqrTo(r,r2);
|
||||
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
|
||||
else { var t = r; r = r2; r2 = t; }
|
||||
}
|
||||
return z.revert(r);
|
||||
}
|
||||
|
||||
// (public) this^e % m, 0 <= e < 2^32
|
||||
function bnModPowInt(e,m) {
|
||||
var z;
|
||||
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
|
||||
return this.exp(e,z);
|
||||
}
|
||||
|
||||
// protected
|
||||
BigInteger.prototype.copyTo = bnpCopyTo;
|
||||
BigInteger.prototype.fromInt = bnpFromInt;
|
||||
BigInteger.prototype.fromString = bnpFromString;
|
||||
BigInteger.prototype.clamp = bnpClamp;
|
||||
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
|
||||
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
|
||||
BigInteger.prototype.lShiftTo = bnpLShiftTo;
|
||||
BigInteger.prototype.rShiftTo = bnpRShiftTo;
|
||||
BigInteger.prototype.subTo = bnpSubTo;
|
||||
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
|
||||
BigInteger.prototype.squareTo = bnpSquareTo;
|
||||
BigInteger.prototype.divRemTo = bnpDivRemTo;
|
||||
BigInteger.prototype.invDigit = bnpInvDigit;
|
||||
BigInteger.prototype.isEven = bnpIsEven;
|
||||
BigInteger.prototype.exp = bnpExp;
|
||||
|
||||
// public
|
||||
BigInteger.prototype.toString = bnToString;
|
||||
BigInteger.prototype.negate = bnNegate;
|
||||
BigInteger.prototype.abs = bnAbs;
|
||||
BigInteger.prototype.compareTo = bnCompareTo;
|
||||
BigInteger.prototype.bitLength = bnBitLength;
|
||||
BigInteger.prototype.mod = bnMod;
|
||||
BigInteger.prototype.modPowInt = bnModPowInt;
|
||||
|
||||
// "constants"
|
||||
BigInteger.ZERO = nbv(0);
|
||||
BigInteger.ONE = nbv(1);
|
||||
88
js/nodeutils.js
Normal file
88
js/nodeutils.js
Normal file
@@ -0,0 +1,88 @@
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var utils = require("./utils.js");
|
||||
|
||||
// Empty a directory.
|
||||
var emptyPath = function(dirPath, done) {
|
||||
fs.readdir(dirPath, function(err, files) {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
utils.mapOr(rmPath, files.map(function(f) { return path.join(dirPath, f); }), done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Make a directory and sub-directories.
|
||||
var mkPath = function(dirPath, mode, done) {
|
||||
fs.mkdir(dirPath, typeof mode === "string" ? parseInt(mode, 8) : mode, function(e) {
|
||||
if (!e || e.code === "EEXIST") {
|
||||
// Created or already exists, done.
|
||||
done();
|
||||
}
|
||||
else if (e.code === "ENOENT") {
|
||||
// Missing sub dir.
|
||||
|
||||
mkPath(path.dirname(dirPath), mode, function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
mkPath(dirPath, mode, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Create directory if needed and empty if needed.
|
||||
var resetPath = function(dirPath, mode, done) {
|
||||
mkPath(dirPath, mode, function(e) {
|
||||
if (e) {
|
||||
done(e);
|
||||
}
|
||||
else {
|
||||
emptyPath(dirPath, done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Remove path recursively.
|
||||
var rmPath = function(dirPath, done) {
|
||||
// console.log("rmPath: %s", dirPath);
|
||||
|
||||
fs.lstat(dirPath, function(err, stats) {
|
||||
if (err && err.code == "ENOENT") {
|
||||
done();
|
||||
}
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else if (stats.isDirectory()) {
|
||||
emptyPath(dirPath, function(e) {
|
||||
if (e) {
|
||||
done(e);
|
||||
}
|
||||
else {
|
||||
// console.log("rmdir: %s", dirPath); done();
|
||||
fs.rmdir(dirPath, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// console.log("unlink: %s", dirPath); done();
|
||||
fs.unlink(dirPath, done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.mkPath = mkPath;
|
||||
exports.resetPath = resetPath;
|
||||
exports.rmPath = rmPath;
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
90
js/remote.js
90
js/remote.js
@@ -7,10 +7,15 @@
|
||||
// YYY A better model might be to allow requesting a target state: keep connected or not.
|
||||
//
|
||||
|
||||
var util = require('util');
|
||||
// Node
|
||||
var util = require('util');
|
||||
|
||||
// npm
|
||||
var WebSocket = require('ws');
|
||||
|
||||
var amount = require('./amount.js');
|
||||
var Amount = amount.Amount;
|
||||
|
||||
// --> trusted: truthy, if remote is trusted
|
||||
var Remote = function (trusted, websocket_ip, websocket_port, config, trace) {
|
||||
this.trusted = trusted;
|
||||
@@ -57,10 +62,10 @@ var flags = {
|
||||
|
||||
// XXX This needs to be determined from the network.
|
||||
var fees = {
|
||||
'default' : 100,
|
||||
'account_create' : 1000,
|
||||
'nickname_create' : 1000,
|
||||
'offer' : 100,
|
||||
'default' : Amount.from_json("100"),
|
||||
'account_create' : Amount.from_json("1000"),
|
||||
'nickname_create' : Amount.from_json("1000"),
|
||||
'offer' : Amount.from_json("100"),
|
||||
};
|
||||
|
||||
Remote.prototype.connect_helper = function () {
|
||||
@@ -383,40 +388,79 @@ Remote.prototype.dirty_account_root = function (account) {
|
||||
// Transactions
|
||||
//
|
||||
|
||||
Remote.prototype.ripple_line_set = function (secret, src, dst, amount, onDone) {
|
||||
Remote.prototype.offer_create = function (secret, src, taker_pays, taker_gets, expiration, onDone) {
|
||||
var secret = this.config.accounts[src] ? this.config.accounts[src].secret : secret;
|
||||
var src_account = this.config.accounts[src] ? this.config.accounts[src].account : src;
|
||||
var dst_account = this.config.accounts[dst] ? this.config.accounts[dst].account : dst;
|
||||
|
||||
var transaction = {
|
||||
'TransactionType' : 'OfferCreate',
|
||||
'Account' : src_account,
|
||||
'Fee' : fees.offer.to_json(),
|
||||
'TakerPays' : taker_pays.to_json(),
|
||||
'TakerGets' : taker_gets.to_json(),
|
||||
};
|
||||
|
||||
if (expiration)
|
||||
transaction.Expiration = expiration;
|
||||
|
||||
this.submit_seq(
|
||||
{
|
||||
'transaction' : {
|
||||
'TransactionType' : 'CreditSet',
|
||||
'Account' : src_account,
|
||||
'Destination' : dst_account,
|
||||
'Fee' : create ? fees.account_create : fees['default'],
|
||||
'Amount' : amount,
|
||||
},
|
||||
'transaction' : transaction,
|
||||
'secret' : secret,
|
||||
}, function () {
|
||||
}, onDone);
|
||||
};
|
||||
|
||||
Remote.prototype.send_xns = function (secret, src, dst, amount, create, onDone) {
|
||||
Remote.prototype.ripple_line_set = function (secret, src, limit, quaility_in, quality_out, onDone) {
|
||||
var secret = this.config.accounts[src] ? this.config.accounts[src].secret : secret;
|
||||
var src_account = this.config.accounts[src] ? this.config.accounts[src].account : src;
|
||||
|
||||
var transaction = {
|
||||
'TransactionType' : 'CreditSet',
|
||||
'Account' : src_account,
|
||||
'Fee' : fees['default'].to_json(),
|
||||
};
|
||||
|
||||
if (limit)
|
||||
transaction.LimitAmount = limit.to_json();
|
||||
|
||||
if (quaility_in)
|
||||
transaction.QualityIn = quaility_in;
|
||||
|
||||
if (quaility_out)
|
||||
transaction.QualityOut = quaility_out;
|
||||
|
||||
this.submit_seq(
|
||||
{
|
||||
'transaction' : transaction,
|
||||
'secret' : secret,
|
||||
}, function () {
|
||||
}, onDone);
|
||||
};
|
||||
|
||||
// --> create: is only valid if destination gets XNS.
|
||||
Remote.prototype.send = function (secret, src, dst, deliver_amount, send_max, create, onDone) {
|
||||
var secret = this.config.accounts[src] ? this.config.accounts[src].secret : secret;
|
||||
var src_account = this.config.accounts[src] ? this.config.accounts[src].account : src;
|
||||
var dst_account = this.config.accounts[dst] ? this.config.accounts[dst].account : dst;
|
||||
|
||||
var transaction = {
|
||||
'TransactionType' : 'Payment',
|
||||
'Account' : src_account,
|
||||
'Fee' : (create ? fees.account_create : fees['default']).to_json(),
|
||||
'Destination' : dst_account,
|
||||
'Amount' : deliver_amount.to_json(),
|
||||
};
|
||||
|
||||
if (create)
|
||||
transaction.Flags = flags.tfCreateAccount;
|
||||
|
||||
if (send_max)
|
||||
transaction.SendMax = send_max.to_json();
|
||||
|
||||
this.submit_seq(
|
||||
{
|
||||
'transaction' : {
|
||||
'TransactionType' : 'Payment',
|
||||
'Account' : src_account,
|
||||
'Destination' : dst_account,
|
||||
'Fee' : create ? fees.account_create : fees['default'],
|
||||
'Flags' : create ? flags.tfCreateAccount : 0,
|
||||
'Amount' : amount,
|
||||
},
|
||||
'transaction' : transaction,
|
||||
'secret' : secret,
|
||||
}, function () {
|
||||
}, onDone);
|
||||
|
||||
87
js/utils.js
87
js/utils.js
@@ -1,8 +1,3 @@
|
||||
// YYY Should probably have two versions: node vs browser
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
Function.prototype.method = function(name,func) {
|
||||
this.prototype[name] = func;
|
||||
|
||||
@@ -42,84 +37,6 @@ var mapOr = function(func, array, done) {
|
||||
}
|
||||
};
|
||||
|
||||
// Make a directory and sub-directories.
|
||||
var mkPath = function(dirPath, mode, done) {
|
||||
fs.mkdir(dirPath, typeof mode === "string" ? parseInt(mode, 8) : mode, function(e) {
|
||||
if (!e || e.code === "EEXIST") {
|
||||
// Created or already exists, done.
|
||||
done();
|
||||
}
|
||||
else if (e.code === "ENOENT") {
|
||||
// Missing sub dir.
|
||||
|
||||
mkPath(path.dirname(dirPath), mode, function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
mkPath(dirPath, mode, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Empty a directory.
|
||||
var emptyPath = function(dirPath, done) {
|
||||
fs.readdir(dirPath, function(err, files) {
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else {
|
||||
mapOr(rmPath, files.map(function(f) { return path.join(dirPath, f); }), done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Remove path recursively.
|
||||
var rmPath = function(dirPath, done) {
|
||||
// console.log("rmPath: %s", dirPath);
|
||||
|
||||
fs.lstat(dirPath, function(err, stats) {
|
||||
if (err && err.code == "ENOENT") {
|
||||
done();
|
||||
}
|
||||
if (err) {
|
||||
done(err);
|
||||
}
|
||||
else if (stats.isDirectory()) {
|
||||
emptyPath(dirPath, function(e) {
|
||||
if (e) {
|
||||
done(e);
|
||||
}
|
||||
else {
|
||||
// console.log("rmdir: %s", dirPath); done();
|
||||
fs.rmdir(dirPath, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// console.log("unlink: %s", dirPath); done();
|
||||
fs.unlink(dirPath, done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Create directory if needed and empty if needed.
|
||||
var resetPath = function(dirPath, mode, done) {
|
||||
mkPath(dirPath, mode, function(e) {
|
||||
if (e) {
|
||||
done(e);
|
||||
}
|
||||
else {
|
||||
emptyPath(dirPath, done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var trace = function(comment, func) {
|
||||
return function() {
|
||||
console.log("%s: %s", trace, arguments.toString);
|
||||
@@ -151,11 +68,7 @@ var stringToHex = function (s) {
|
||||
}).join("");
|
||||
};
|
||||
|
||||
exports.emptyPath = emptyPath;
|
||||
exports.mapOr = mapOr;
|
||||
exports.mkPath = mkPath;
|
||||
exports.resetPath = resetPath;
|
||||
exports.rmPath = rmPath;
|
||||
exports.trace = trace;
|
||||
exports.hexToString = hexToString;
|
||||
exports.stringToHex = stringToHex;
|
||||
|
||||
@@ -1131,15 +1131,13 @@ Json::Value STAmount::getJson(int) const
|
||||
{
|
||||
Json::Value elem(Json::objectValue);
|
||||
|
||||
// This is a hack, many places don't specify a currency. STAmount is used just as a value.
|
||||
if (!mIsNative)
|
||||
{
|
||||
// It is an error for currency or issuer not to be specified for valid json.
|
||||
|
||||
elem["value"] = getText();
|
||||
elem["currency"] = getHumanCurrency();
|
||||
|
||||
if (!mIssuer.isZero())
|
||||
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
|
||||
|
||||
elem["issuer"] = NewcoinAddress::createHumanAccountID(mIssuer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
54
src/Peer.cpp
54
src/Peer.cpp
@@ -540,7 +540,7 @@ void Peer::processReadBuffer()
|
||||
break;
|
||||
|
||||
#endif
|
||||
case newcoin::mtGET_OBJECT:
|
||||
case newcoin::mtGET_OBJECTS:
|
||||
{
|
||||
newcoin::TMGetObjectByHash msg;
|
||||
if (msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||
@@ -549,15 +549,6 @@ void Peer::processReadBuffer()
|
||||
}
|
||||
break;
|
||||
|
||||
case newcoin::mtOBJECT:
|
||||
{
|
||||
newcoin::TMObjectByHash msg;
|
||||
if (msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||
recvObjectByHash(msg);
|
||||
else std::cerr << "parse error: " << type << std::endl;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "Unknown Msg: " << type << std::endl;
|
||||
std::cerr << strHex(&mReadbuf[0], mReadbuf.size());
|
||||
@@ -872,16 +863,45 @@ void Peer::recvPeers(newcoin::TMPeers& packet)
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::recvIndexedObject(newcoin::TMIndexedObject& packet)
|
||||
{
|
||||
}
|
||||
|
||||
void Peer::recvGetObjectByHash(newcoin::TMGetObjectByHash& packet)
|
||||
{
|
||||
}
|
||||
if (packet.query())
|
||||
{ // this is a query
|
||||
newcoin::TMGetObjectByHash reply;
|
||||
|
||||
void Peer::recvObjectByHash(newcoin::TMObjectByHash& packet)
|
||||
{
|
||||
reply.clear_query();
|
||||
if (packet.has_seq())
|
||||
reply.set_seq(packet.seq());
|
||||
reply.set_type(packet.type());
|
||||
if (packet.has_ledgerhash())
|
||||
reply.set_ledgerhash(packet.ledgerhash());
|
||||
|
||||
// This is a very minimal implementation
|
||||
for (unsigned i = 0; i < packet.objects_size(); ++i)
|
||||
{
|
||||
uint256 hash;
|
||||
const newcoin::TMIndexedObject& obj = packet.objects(i);
|
||||
if (obj.has_hash() && (obj.hash().size() == (256/8)))
|
||||
{
|
||||
memcpy(hash.begin(), obj.hash().data(), 256 / 8);
|
||||
HashedObject::pointer hObj = theApp->getHashedObjectStore().retrieve(hash);
|
||||
if (hObj)
|
||||
{
|
||||
newcoin::TMIndexedObject& newObj = *reply.add_objects();
|
||||
newObj.set_hash(hash.begin(), hash.size());
|
||||
newObj.set_data(&hObj->getData().front(), hObj->getData().size());
|
||||
if (obj.has_nodeid())
|
||||
newObj.set_index(obj.nodeid());
|
||||
}
|
||||
}
|
||||
}
|
||||
cLog(lsDEBUG) << "GetObjByHash query: had " << reply.objects_size() << " of " << packet.objects_size();
|
||||
sendPacket(boost::make_shared<PackedMessage>(packet, newcoin::mtGET_OBJECTS));
|
||||
}
|
||||
else
|
||||
{ // this is a reply
|
||||
// WRITEME
|
||||
}
|
||||
}
|
||||
|
||||
void Peer::recvPing(newcoin::TMPing& packet)
|
||||
|
||||
@@ -102,9 +102,7 @@ protected:
|
||||
void recvGetContacts(newcoin::TMGetContacts& packet);
|
||||
void recvGetPeers(newcoin::TMGetPeers& packet);
|
||||
void recvPeers(newcoin::TMPeers& packet);
|
||||
void recvIndexedObject(newcoin::TMIndexedObject& packet);
|
||||
void recvGetObjectByHash(newcoin::TMGetObjectByHash& packet);
|
||||
void recvObjectByHash(newcoin::TMObjectByHash& packet);
|
||||
void recvPing(newcoin::TMPing& packet);
|
||||
void recvErrorMessage(newcoin::TMErrorMsg& packet);
|
||||
void recvSearchTransaction(newcoin::TMSearchTransaction& packet);
|
||||
|
||||
@@ -518,7 +518,7 @@ std::ostream& operator<<(std::ostream& out, const SHAMapMissingNode& mn)
|
||||
out << "Missing/STA(" << mn.getNodeID() << ")";
|
||||
else
|
||||
out << "Missing/" << mn.getNodeID();
|
||||
return(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ enum MessageType {
|
||||
// data replication and synchronization
|
||||
mtGET_VALIDATIONS = 40;
|
||||
mtVALIDATION = 41;
|
||||
mtGET_OBJECT = 42;
|
||||
mtOBJECT = 43;
|
||||
mtGET_OBJECTS = 42;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,34 +192,31 @@ message TMAccount{
|
||||
|
||||
message TMIndexedObject
|
||||
{
|
||||
enum ObjectType {
|
||||
otTRANSACTION = 1;
|
||||
otTRANSACTION_NODE = 2; // a node in a transaction tree
|
||||
otTRANSACTION_LEAF = 3; // a leaf in a transaction tree
|
||||
otACCOUNT = 4; // a single account state (with balance/sequence)
|
||||
otACCOUNT_NODE = 5; // a node in an account state tree
|
||||
otACCOUNT_LEAF = 6; // a leaf in an account state tree
|
||||
otLEDGER = 7;
|
||||
}
|
||||
|
||||
required bytes hash = 1;
|
||||
required ObjectType type = 2;
|
||||
optional bytes hash = 1;
|
||||
optional bytes nodeID = 2;
|
||||
optional bytes index = 3;
|
||||
optional bytes data = 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
message TMGetObjectByHash
|
||||
{
|
||||
required TMIndexedObject object = 1;
|
||||
optional uint32 seq = 2; // used to match replies to queries
|
||||
enum ObjectType {
|
||||
otUNKNOWN = 0;
|
||||
otLEDGER = 1;
|
||||
otTRANSACTION = 2;
|
||||
otTRANSACTION_NODE = 3;
|
||||
otSTATE_NODE = 4;
|
||||
otCAS_OBJECT = 5;
|
||||
}
|
||||
|
||||
required ObjectType type = 1;
|
||||
required bool query = 2; // is this a query or a reply?
|
||||
optional uint32 seq = 3; // used to match replies to queries
|
||||
optional bytes ledgerHash = 4; // the hash of the ledger these queries are for
|
||||
optional bool fat = 5; // return related nodes
|
||||
repeated TMIndexedObject objects = 6; // the specific objects requested
|
||||
}
|
||||
|
||||
message TMObjectByHash
|
||||
{
|
||||
optional TMIndexedObject object = 1; // present unless no object found
|
||||
optional bytes data = 2; // present unless no object found
|
||||
optional uint32 seq = 3; // matches seq from query
|
||||
}
|
||||
|
||||
message TMLedgerNode {
|
||||
required bytes nodedata = 1;
|
||||
|
||||
34
test/amount-test.js
Normal file
34
test/amount-test.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var buster = require("buster");
|
||||
|
||||
var amount = require("../js/amount.js");
|
||||
|
||||
buster.testCase("Amount", {
|
||||
"UInt160" : {
|
||||
"Parse 0" : function () {
|
||||
buster.assert.equals(0, amount.UInt160.from_json("0").value);
|
||||
},
|
||||
"Parse 0 export" : function () {
|
||||
buster.assert.equals(amount.consts.hex_xns, amount.UInt160.from_json("0").to_json());
|
||||
},
|
||||
"Parse native 123" : function () {
|
||||
buster.assert.equals("123/XNS", amount.Amount.from_json("123").to_text_full());
|
||||
},
|
||||
"Parse native 12.3" : function () {
|
||||
buster.assert.equals("12300000/XNS", amount.Amount.from_json("12.3").to_text_full());
|
||||
},
|
||||
"Parse 123./USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh" : function () {
|
||||
buster.assert.equals("123/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh", amount.Amount.from_json("123./USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh").to_text_full());
|
||||
},
|
||||
"Parse 12300/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh" : function () {
|
||||
buster.assert.equals("12300/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh", amount.Amount.from_json("12300/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh").to_text_full());
|
||||
},
|
||||
"Parse 12.3/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh" : function () {
|
||||
buster.assert.equals("12.3/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh", amount.Amount.from_json("12.3/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh").to_text_full());
|
||||
},
|
||||
"Parse 1.2300/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh" : function () {
|
||||
buster.assert.equals("1.23/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh", amount.Amount.from_json("1.2300/USD/iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh").to_text_full());
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
196
test/server.js
196
test/server.js
@@ -8,148 +8,148 @@
|
||||
// Servers are created in tmp/server/$server
|
||||
//
|
||||
|
||||
var config = require("./config.js");
|
||||
var utils = require("../js/utils.js");
|
||||
var config = require("./config.js");
|
||||
var nodeutils = require("../js/nodeutils.js");
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var util = require("util");
|
||||
var child = require("child_process");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var util = require("util");
|
||||
var child = require("child_process");
|
||||
|
||||
var servers = {};
|
||||
|
||||
// Create a server object
|
||||
var Server = function(name) {
|
||||
this.name = name;
|
||||
this.name = name;
|
||||
};
|
||||
|
||||
// Return a server's newcoind.cfg as string.
|
||||
Server.method('configContent', function() {
|
||||
var cfg = config.servers[this.name];
|
||||
Server.prototype.configContent = function() {
|
||||
var cfg = config.servers[this.name];
|
||||
|
||||
return Object.keys(cfg).map(function(o) {
|
||||
return util.format("[%s]\n%s\n", o, cfg[o]);
|
||||
}).join("");
|
||||
});
|
||||
return Object.keys(cfg).map(function(o) {
|
||||
return util.format("[%s]\n%s\n", o, cfg[o]);
|
||||
}).join("");
|
||||
};
|
||||
|
||||
Server.method('serverPath', function() {
|
||||
Server.prototype.serverPath = function() {
|
||||
return "tmp/server/" + this.name;
|
||||
});
|
||||
};
|
||||
|
||||
Server.method('configPath', function() {
|
||||
return path.join(this.serverPath(), "newcoind.cfg");
|
||||
});
|
||||
Server.prototype.configPath = function() {
|
||||
return path.join(this.serverPath(), "newcoind.cfg");
|
||||
};
|
||||
|
||||
// Write a server's newcoind.cfg.
|
||||
Server.method('writeConfig', function(done) {
|
||||
fs.writeFile(this.configPath(), this.configContent(), 'utf8', done);
|
||||
});
|
||||
Server.prototype.writeConfig = function(done) {
|
||||
fs.writeFile(this.configPath(), this.configContent(), 'utf8', done);
|
||||
};
|
||||
|
||||
// Spawn the server.
|
||||
Server.method('serverSpawnSync', function() {
|
||||
// Spawn in standalone mode for now.
|
||||
this.child = child.spawn(
|
||||
config.newcoind,
|
||||
[
|
||||
"-a",
|
||||
"-v",
|
||||
"--conf=newcoind.cfg"
|
||||
],
|
||||
{
|
||||
cwd: this.serverPath(),
|
||||
env: process.env,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
Server.prototype.serverSpawnSync = function() {
|
||||
// Spawn in standalone mode for now.
|
||||
this.child = child.spawn(
|
||||
config.newcoind,
|
||||
[
|
||||
"-a",
|
||||
"-v",
|
||||
"--conf=newcoind.cfg"
|
||||
],
|
||||
{
|
||||
cwd: this.serverPath(),
|
||||
env: process.env,
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
console.log("server: start %s: %s -a --conf=%s", this.child.pid, config.newcoind, this.configPath());
|
||||
console.log("server: start %s: %s -a --conf=%s", this.child.pid, config.newcoind, this.configPath());
|
||||
|
||||
// By default, just log exits.
|
||||
this.child.on('exit', function(code, signal) {
|
||||
// If could not exec: code=127, signal=null
|
||||
// If regular exit: code=0, signal=null
|
||||
console.log("server: spawn: server exited code=%s: signal=%s", code, signal);
|
||||
});
|
||||
// By default, just log exits.
|
||||
this.child.on('exit', function(code, signal) {
|
||||
// If could not exec: code=127, signal=null
|
||||
// If regular exit: code=0, signal=null
|
||||
console.log("server: spawn: server exited code=%s: signal=%s", code, signal);
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
// Prepare server's working directory.
|
||||
Server.method('makeBase', function(done) {
|
||||
Server.prototype.makeBase = function(done) {
|
||||
var path = this.serverPath();
|
||||
var self = this;
|
||||
var self = this;
|
||||
|
||||
// Reset the server directory, build it if needed.
|
||||
utils.resetPath(path, '0777', function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
self.writeConfig(done);
|
||||
}
|
||||
});
|
||||
});
|
||||
nodeutils.resetPath(path, '0777', function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
self.writeConfig(done);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Create a standalone server.
|
||||
// Prepare the working directory and spawn the server.
|
||||
Server.method('start', function(done) {
|
||||
var self = this;
|
||||
Server.prototype.start = function(done) {
|
||||
var self = this;
|
||||
|
||||
this.makeBase(function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
self.serverSpawnSync();
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
self.serverSpawnSync();
|
||||
done();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Stop a standalone server.
|
||||
Server.method('stop', function(done) {
|
||||
if (this.child) {
|
||||
// Update the on exit to invoke done.
|
||||
this.child.on('exit', function(code, signal) {
|
||||
console.log("server: stop: server exited");
|
||||
done();
|
||||
});
|
||||
this.child.kill();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("server: stop: no such server");
|
||||
done();
|
||||
}
|
||||
});
|
||||
Server.prototype.stop = function(done) {
|
||||
if (this.child) {
|
||||
// Update the on exit to invoke done.
|
||||
this.child.on('exit', function(code, signal) {
|
||||
console.log("server: stop: server exited");
|
||||
done();
|
||||
});
|
||||
this.child.kill();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("server: stop: no such server");
|
||||
done('noSuchServer');
|
||||
}
|
||||
};
|
||||
|
||||
// Start the named server.
|
||||
exports.start = function(name, done) {
|
||||
if (servers[name])
|
||||
{
|
||||
console.log("server: start: server already started.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var server = new Server(name);
|
||||
if (servers[name])
|
||||
{
|
||||
console.log("server: start: server already started.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var server = new Server(name);
|
||||
|
||||
servers[name] = server;
|
||||
servers[name] = server;
|
||||
|
||||
console.log("server: start: %s", JSON.stringify(server));
|
||||
console.log("server: start: %s", JSON.stringify(server));
|
||||
|
||||
server.start(done);
|
||||
}
|
||||
server.start(done);
|
||||
}
|
||||
};
|
||||
|
||||
// Delete the named server.
|
||||
exports.stop = function(name, done) {
|
||||
console.log("server: stop: %s of %s", name, Object.keys(servers).toString());
|
||||
console.log("server: stop: %s of %s", name, Object.keys(servers).toString());
|
||||
|
||||
var server = servers[name];
|
||||
if (server) {
|
||||
server.stop(done);
|
||||
delete servers[name];
|
||||
}
|
||||
var server = servers[name];
|
||||
if (server) {
|
||||
server.stop(done);
|
||||
delete servers[name];
|
||||
}
|
||||
};
|
||||
|
||||
exports.Server = Server;
|
||||
|
||||
// vim:ts=4
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
var fs = require("fs");
|
||||
var buster = require("buster");
|
||||
|
||||
var server = require("./server.js");
|
||||
var remote = require("../js/remote.js");
|
||||
var config = require("./config.js");
|
||||
var server = require("./server.js");
|
||||
var amount = require("../js/amount.js");
|
||||
var remote = require("../js/remote.js");
|
||||
|
||||
var Amount = amount.Amount;
|
||||
|
||||
// How long to wait for server to start.
|
||||
var serverDelay = 1500;
|
||||
@@ -114,8 +116,8 @@ buster.testCase("Websocket commands", {
|
||||
|
||||
alpha.request_ledger_entry({
|
||||
'ledger_closed' : r.ledger_closed,
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh'
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh'
|
||||
} , function (r) {
|
||||
// console.log("account_root: %s", JSON.stringify(r));
|
||||
|
||||
@@ -134,8 +136,8 @@ buster.testCase("Websocket commands", {
|
||||
|
||||
alpha.request_ledger_entry({
|
||||
'ledger_closed' : r.ledger_closed,
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'foobar'
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'foobar'
|
||||
} , function (r) {
|
||||
// console.log("account_root: %s", JSON.stringify(r));
|
||||
|
||||
@@ -154,8 +156,8 @@ buster.testCase("Websocket commands", {
|
||||
|
||||
alpha.request_ledger_entry({
|
||||
'ledger_closed' : r.ledger_closed,
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn'
|
||||
'type' : 'account_root',
|
||||
'account_root' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn'
|
||||
}, function (r) {
|
||||
console.log("account_root: %s", JSON.stringify(r));
|
||||
|
||||
@@ -174,8 +176,8 @@ buster.testCase("Websocket commands", {
|
||||
|
||||
alpha.request_ledger_entry({
|
||||
'ledger_closed' : r.ledger_closed,
|
||||
'type' : 'account_root',
|
||||
'index' : "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8",
|
||||
'type' : 'account_root',
|
||||
'index' : "2B6AC232AA4C4BE41BF49D2459FA4A0347E1B543A4C92FCEE0821C0201E2E9A8",
|
||||
} , function (r) {
|
||||
console.log("node: %s", JSON.stringify(r));
|
||||
|
||||
@@ -187,7 +189,7 @@ buster.testCase("Websocket commands", {
|
||||
|
||||
'create account' :
|
||||
function (done) {
|
||||
alpha.send_xns(undefined, 'root', 'alice', 10000, true, function (r) {
|
||||
alpha.send(undefined, 'root', 'alice', Amount.from_json("10000"), undefined, 'CREATE', function (r) {
|
||||
console.log(r);
|
||||
|
||||
buster.refute(r.error);
|
||||
|
||||
Reference in New Issue
Block a user