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/Application.cpp
This commit is contained in:
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,9 @@
|
||||
[submodule "websocketpp"]
|
||||
path = websocketpp
|
||||
url = https://github.com/zaphoyd/websocketpp.git
|
||||
[submodule "js/cryptojs"]
|
||||
path = js/cryptojs
|
||||
url = git://github.com/gwjjeff/cryptojs.git
|
||||
[submodule "js/sjcl"]
|
||||
path = js/sjcl
|
||||
url = git://github.com/bitwiseshiftleft/sjcl.git
|
||||
|
||||
8
README
8
README
@@ -2,5 +2,9 @@ Dependancies:
|
||||
- boost 1.47
|
||||
- Google protocol buffers 2.4.1
|
||||
- openssl
|
||||
- mysql
|
||||
- websocketpp
|
||||
|
||||
Sub modules:
|
||||
- websocketpp: https://github.com/zaphoyd/websocketpp
|
||||
- sjcl: https://github.com/bitwiseshiftleft/sjcl
|
||||
- cryptojs: https://github.com/gwjjeff/cryptojs
|
||||
aka http://code.google.com/p/crypto-js/
|
||||
|
||||
96
SConstruct
96
SConstruct
@@ -3,16 +3,22 @@
|
||||
#
|
||||
|
||||
import glob
|
||||
import platform
|
||||
|
||||
CTAGS = '/usr/bin/exuberant-ctags'
|
||||
OSX = bool(platform.mac_ver()[0])
|
||||
|
||||
if OSX:
|
||||
CTAGS = '/usr/bin/ctags'
|
||||
else:
|
||||
CTAGS = '/usr/bin/exuberant-ctags'
|
||||
|
||||
#
|
||||
# scons tools
|
||||
#
|
||||
|
||||
env = Environment(
|
||||
tools = ['default', 'protoc']
|
||||
)
|
||||
tools = ['default', 'protoc']
|
||||
)
|
||||
|
||||
# Use clang
|
||||
#env.Replace(CC = 'clang')
|
||||
@@ -23,73 +29,83 @@ env = Environment(
|
||||
#
|
||||
ctags = Builder(action = '$CTAGS $CTAGSOPTIONS -f $TARGET $SOURCES')
|
||||
env.Append(BUILDERS = { 'CTags' : ctags })
|
||||
env.Replace(CTAGS = CTAGS, CTAGSOPTIONS = '--tag-relative')
|
||||
if OSX:
|
||||
env.Replace(CTAGS = CTAGS)
|
||||
else:
|
||||
env.Replace(CTAGS = CTAGS, CTAGSOPTIONS = '--tag-relative')
|
||||
|
||||
#
|
||||
# Put objects files in their own directory.
|
||||
#
|
||||
for dir in ['src', 'database', 'json', 'websocketpp']:
|
||||
VariantDir('obj/'+dir, dir, duplicate=0)
|
||||
VariantDir('obj/'+dir, dir, duplicate=0)
|
||||
|
||||
# Use openssl
|
||||
env.ParseConfig('pkg-config --cflags --libs openssl')
|
||||
|
||||
env.Append(LIBS = [
|
||||
'boost_date_time-mt',
|
||||
'boost_filesystem-mt',
|
||||
'boost_program_options-mt',
|
||||
'boost_regex-mt',
|
||||
'boost_system-mt',
|
||||
'boost_thread-mt',
|
||||
'protobuf',
|
||||
'dl', # dynamic linking
|
||||
'z'
|
||||
])
|
||||
env.Append(
|
||||
LIBS = [
|
||||
'boost_date_time-mt',
|
||||
'boost_filesystem-mt',
|
||||
'boost_program_options-mt',
|
||||
'boost_regex-mt',
|
||||
'boost_system-mt',
|
||||
'boost_thread-mt',
|
||||
'protobuf',
|
||||
'dl', # dynamic linking
|
||||
'z'
|
||||
]
|
||||
)
|
||||
|
||||
DEBUGFLAGS = ['-g', '-DDEBUG']
|
||||
BOOSTFLAGS = ['-DBOOST_TEST_DYN_LINK', '-DBOOST_FILESYSTEM_NO_DEPRECATED']
|
||||
DEBUGFLAGS = ['-g', '-DDEBUG']
|
||||
BOOSTFLAGS = ['-DBOOST_TEST_DYN_LINK', '-DBOOST_FILESYSTEM_NO_DEPRECATED']
|
||||
|
||||
env.Append(LINKFLAGS = ['-rdynamic', '-pthread'])
|
||||
env.Append(CCFLAGS = ['-pthread', '-Wall', '-Wno-sign-compare', '-Wno-char-subscripts', '-DSQLITE_THREADSAFE'])
|
||||
env.Append(CXXFLAGS = ['-O0', '-pthread', '-Wno-invalid-offsetof', '-Wformat']+BOOSTFLAGS+DEBUGFLAGS)
|
||||
|
||||
DB_SRCS = glob.glob('database/*.c') + glob.glob('database/*.cpp')
|
||||
JSON_SRCS = glob.glob('json/*.cpp')
|
||||
WEBSOCKETPP_SRCS = [
|
||||
'websocketpp/src/base64/base64.cpp',
|
||||
'websocketpp/src/md5/md5.c',
|
||||
'websocketpp/src/messages/data.cpp',
|
||||
'websocketpp/src/network_utilities.cpp',
|
||||
'websocketpp/src/processors/hybi_header.cpp',
|
||||
'websocketpp/src/processors/hybi_util.cpp',
|
||||
'websocketpp/src/sha1/sha1.cpp',
|
||||
'websocketpp/src/uri.cpp'
|
||||
]
|
||||
if OSX:
|
||||
env.Append(LINKFLAGS = ['-L/usr/local/Cellar/openssl/1.0.1c/lib'])
|
||||
env.Append(CXXFLAGS = ['-I/usr/local/Cellar/openssl/1.0.1c/include'])
|
||||
|
||||
NEWCOIN_SRCS = glob.glob('src/*.cpp')
|
||||
PROTO_SRCS = env.Protoc([], 'src/newcoin.proto', PROTOCOUTDIR='obj', PROTOCPYTHONOUTDIR=None)
|
||||
DB_SRCS = glob.glob('database/*.c') + glob.glob('database/*.cpp')
|
||||
JSON_SRCS = glob.glob('json/*.cpp')
|
||||
|
||||
WEBSOCKETPP_SRCS = [
|
||||
'websocketpp/src/base64/base64.cpp',
|
||||
'websocketpp/src/md5/md5.c',
|
||||
'websocketpp/src/messages/data.cpp',
|
||||
'websocketpp/src/network_utilities.cpp',
|
||||
'websocketpp/src/processors/hybi_header.cpp',
|
||||
'websocketpp/src/processors/hybi_util.cpp',
|
||||
'websocketpp/src/sha1/sha1.cpp',
|
||||
'websocketpp/src/uri.cpp'
|
||||
]
|
||||
|
||||
NEWCOIN_SRCS = glob.glob('src/*.cpp')
|
||||
PROTO_SRCS = env.Protoc([], 'src/newcoin.proto', PROTOCOUTDIR='obj', PROTOCPYTHONOUTDIR=None)
|
||||
|
||||
env.Clean(PROTO_SRCS, 'site_scons/site_tools/protoc.pyc')
|
||||
|
||||
# Remove unused source files.
|
||||
UNUSED_SRCS = ['src/HttpReply.cpp']
|
||||
UNUSED_SRCS = ['src/HttpReply.cpp']
|
||||
|
||||
for file in UNUSED_SRCS:
|
||||
NEWCOIN_SRCS.remove(file)
|
||||
NEWCOIN_SRCS.remove(file)
|
||||
|
||||
NEWCOIN_SRCS += DB_SRCS + JSON_SRCS + WEBSOCKETPP_SRCS
|
||||
NEWCOIN_SRCS += DB_SRCS + JSON_SRCS + WEBSOCKETPP_SRCS
|
||||
|
||||
# Derive the object files from the source files.
|
||||
NEWCOIN_OBJS = []
|
||||
NEWCOIN_OBJS = []
|
||||
|
||||
for file in NEWCOIN_SRCS:
|
||||
NEWCOIN_OBJS.append('obj/' + file)
|
||||
NEWCOIN_OBJS.append('obj/' + file)
|
||||
|
||||
NEWCOIN_OBJS += PROTO_SRCS
|
||||
NEWCOIN_OBJS += PROTO_SRCS
|
||||
|
||||
newcoind = env.Program('newcoind', NEWCOIN_OBJS)
|
||||
newcoind = env.Program('newcoind', NEWCOIN_OBJS)
|
||||
|
||||
tags = env.CTags('obj/tags', NEWCOIN_SRCS)
|
||||
tags = env.CTags('obj/tags', NEWCOIN_SRCS)
|
||||
|
||||
Default(newcoind, tags)
|
||||
|
||||
|
||||
210
js/amount.js
Normal file
210
js/amount.js
Normal file
@@ -0,0 +1,210 @@
|
||||
// Represent Newcoin amounts and currencies.
|
||||
|
||||
|
||||
var utils = require("./utils.js");
|
||||
|
||||
var UInt160 = function () {
|
||||
// Internal form:
|
||||
// 0, 1, 'iXXXXX', 20 byte string, or NaN.
|
||||
// XXX Should standardize on 'i' format or 20 format.
|
||||
};
|
||||
|
||||
// Returns NaN on error.
|
||||
UInt160.prototype.parse_json = function (j) {
|
||||
// Canonicalize and validate
|
||||
|
||||
switch (j) {
|
||||
case undefined:
|
||||
case "0":
|
||||
case exports.consts.address_xns:
|
||||
case exports.consts.uint160_xns:
|
||||
case exports.consts.hex_xns:
|
||||
this.value = 0;
|
||||
break;
|
||||
|
||||
case "1":
|
||||
case exports.consts.address_one:
|
||||
case exports.consts.uint160_one:
|
||||
case exports.consts.hex_one:
|
||||
this.value = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ('string' !== typeof j) {
|
||||
this.value = NaN;
|
||||
}
|
||||
else if (20 === j.length) {
|
||||
this.value = j;
|
||||
}
|
||||
else if (40 === j.length) {
|
||||
this.value = utils.hexToString(j);
|
||||
}
|
||||
else if (j[0] === "i") {
|
||||
// XXX Do more checking convert to string.
|
||||
|
||||
this.value = j;
|
||||
}
|
||||
else {
|
||||
this.value = NaN;
|
||||
}
|
||||
}
|
||||
|
||||
return this.value;
|
||||
};
|
||||
|
||||
// Convert from internal form.
|
||||
// XXX Json form should allow 0 and 1, C++ doesn't currently allow it.
|
||||
UInt160.prototype.to_json = function () {
|
||||
if ("0" === this.value) {
|
||||
return exports.consts.hex_xns;
|
||||
}
|
||||
else if ("1" === this.value)
|
||||
{
|
||||
return exports.consts.hex_one;
|
||||
}
|
||||
else if (20 === this.value.length) {
|
||||
return utils.stringToHex(this.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.value;
|
||||
}
|
||||
};
|
||||
|
||||
var Currency = function () {
|
||||
// Internal form: 0 = XNS. 3 letter-code.
|
||||
// XXX Internal should be 0 or hex.
|
||||
|
||||
// Json form:
|
||||
// '', 'XNS', '0': 0
|
||||
// 3-letter code: ...
|
||||
// XXX Should support hex, C++ doesn't currently allow it.
|
||||
}
|
||||
|
||||
// Returns NaN on error.
|
||||
Currency.prototype.parse_json = function (j) {
|
||||
if ("" === j || "0" === j || "XNS" === j) {
|
||||
this.value = 0;
|
||||
}
|
||||
else if ('string' != typeof j || 3 !== j.length) {
|
||||
this.value = NaN;
|
||||
}
|
||||
else {
|
||||
this.value = j;
|
||||
}
|
||||
|
||||
return this.value;
|
||||
};
|
||||
|
||||
Currency.prototype.to_json = function () {
|
||||
return this.value ? this.value : 'XNS';
|
||||
};
|
||||
|
||||
Currency.prototype.to_human = function() {
|
||||
return this.value ? this.value : 'XNS';
|
||||
};
|
||||
|
||||
var Amount = function () {
|
||||
// Json format:
|
||||
// integer : XNS
|
||||
// { 'value' : ..., 'currency' : ..., 'issuer' : ...}
|
||||
|
||||
this.value = 0;
|
||||
this.offset = 0;
|
||||
this.is_native = false;
|
||||
this.is_negative = false;
|
||||
|
||||
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.prototype.to_json = function() {
|
||||
if (this.is_native) {
|
||||
return this.to_text();
|
||||
}
|
||||
else
|
||||
{
|
||||
return {
|
||||
'value' : this.to_text(),
|
||||
'currency' : this.currency.to_json(),
|
||||
'issuer' : this.issuer.to_json(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Parse a native value.
|
||||
Amount.prototype.parse_native = function(j) {
|
||||
if ('integer' === typeof j) {
|
||||
// XNS
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
this.is_native = true;
|
||||
this.is_negative = j < 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
// Parse a non-native value.
|
||||
Amount.prototype.parse_value = function(j) {
|
||||
if ('integer' === typeof j) {
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
this.is_native = false;
|
||||
this.is_negative = j < 0;
|
||||
}
|
||||
else if ('string' === typeof j) {
|
||||
this.value = j >= 0 ? j : -j; // XXX Use biginteger.
|
||||
this.offset = 0;
|
||||
this.is_native = false;
|
||||
this.is_negative = j < 0;
|
||||
}
|
||||
else {
|
||||
this.value = NaN;
|
||||
}
|
||||
};
|
||||
|
||||
// <-> j
|
||||
Amount.prototype.parse_json = function(j) {
|
||||
if ('object' === typeof j && j.currency) {
|
||||
|
||||
this.parse_value(j);
|
||||
this.currency.parse_json(j.currency);
|
||||
this.issuer.parse_json(j.issuer);
|
||||
}
|
||||
else {
|
||||
this.parse_native(j);
|
||||
this.currency = 0;
|
||||
this.issuer = 0;
|
||||
}
|
||||
};
|
||||
|
||||
exports.Amount = Amount;
|
||||
exports.Currency = Currency;
|
||||
exports.UInt160 = UInt160;
|
||||
|
||||
exports.consts = {
|
||||
'address_xns' : "iiiiiiiiiiiiiiiiiiiiihoLvTp",
|
||||
'address_one' : "iiiiiiiiiiiiiiiiiiiiBZbvjr",
|
||||
'currency_xns' : 0,
|
||||
'currency_one' : 1,
|
||||
'uint160_xns' : hexToString("0000000000000000000000000000000000000000"),
|
||||
'uint160_one' : hexToString("0000000000000000000000000000000000000001"),
|
||||
'hex_xns' : "0000000000000000000000000000000000000000",
|
||||
'hex_one' : "0000000000000000000000000000000000000001",
|
||||
};
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
1
js/cryptojs
Submodule
1
js/cryptojs
Submodule
Submodule js/cryptojs added at c3c843c513
559
js/jsbn/jsbn.js
Normal file
559
js/jsbn/jsbn.js
Normal file
@@ -0,0 +1,559 @@
|
||||
// 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);
|
||||
656
js/jsbn/jsbn2.js
Normal file
656
js/jsbn/jsbn2.js
Normal file
@@ -0,0 +1,656 @@
|
||||
// Copyright (c) 2005-2009 Tom Wu
|
||||
// All Rights Reserved.
|
||||
// See "LICENSE" for details.
|
||||
|
||||
// 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
|
||||
|
||||
// (public)
|
||||
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
|
||||
|
||||
// (public) return value as integer
|
||||
function bnIntValue() {
|
||||
if(this.s < 0) {
|
||||
if(this.t == 1) return this[0]-this.DV;
|
||||
else if(this.t == 0) return -1;
|
||||
}
|
||||
else if(this.t == 1) return this[0];
|
||||
else if(this.t == 0) return 0;
|
||||
// assumes 16 < DB < 32
|
||||
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
|
||||
}
|
||||
|
||||
// (public) return value as byte
|
||||
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
|
||||
|
||||
// (public) return value as short (assumes DB>=16)
|
||||
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
|
||||
|
||||
// (protected) return x s.t. r^x < DV
|
||||
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
|
||||
|
||||
// (public) 0 if this == 0, 1 if this > 0
|
||||
function bnSigNum() {
|
||||
if(this.s < 0) return -1;
|
||||
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
// (protected) convert to radix string
|
||||
function bnpToRadix(b) {
|
||||
if(b == null) b = 10;
|
||||
if(this.signum() == 0 || b < 2 || b > 36) return "0";
|
||||
var cs = this.chunkSize(b);
|
||||
var a = Math.pow(b,cs);
|
||||
var d = nbv(a), y = nbi(), z = nbi(), r = "";
|
||||
this.divRemTo(d,y,z);
|
||||
while(y.signum() > 0) {
|
||||
r = (a+z.intValue()).toString(b).substr(1) + r;
|
||||
y.divRemTo(d,y,z);
|
||||
}
|
||||
return z.intValue().toString(b) + r;
|
||||
}
|
||||
|
||||
// (protected) convert from radix string
|
||||
function bnpFromRadix(s,b) {
|
||||
this.fromInt(0);
|
||||
if(b == null) b = 10;
|
||||
var cs = this.chunkSize(b);
|
||||
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
|
||||
for(var i = 0; i < s.length; ++i) {
|
||||
var x = intAt(s,i);
|
||||
if(x < 0) {
|
||||
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
|
||||
continue;
|
||||
}
|
||||
w = b*w+x;
|
||||
if(++j >= cs) {
|
||||
this.dMultiply(d);
|
||||
this.dAddOffset(w,0);
|
||||
j = 0;
|
||||
w = 0;
|
||||
}
|
||||
}
|
||||
if(j > 0) {
|
||||
this.dMultiply(Math.pow(b,j));
|
||||
this.dAddOffset(w,0);
|
||||
}
|
||||
if(mi) BigInteger.ZERO.subTo(this,this);
|
||||
}
|
||||
|
||||
// (protected) alternate constructor
|
||||
function bnpFromNumber(a,b,c) {
|
||||
if("number" == typeof b) {
|
||||
// new BigInteger(int,int,RNG)
|
||||
if(a < 2) this.fromInt(1);
|
||||
else {
|
||||
this.fromNumber(a,c);
|
||||
if(!this.testBit(a-1)) // force MSB set
|
||||
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
|
||||
if(this.isEven()) this.dAddOffset(1,0); // force odd
|
||||
while(!this.isProbablePrime(b)) {
|
||||
this.dAddOffset(2,0);
|
||||
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// new BigInteger(int,RNG)
|
||||
var x = new Array(), t = a&7;
|
||||
x.length = (a>>3)+1;
|
||||
b.nextBytes(x);
|
||||
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
|
||||
this.fromString(x,256);
|
||||
}
|
||||
}
|
||||
|
||||
// (public) convert to bigendian byte array
|
||||
function bnToByteArray() {
|
||||
var i = this.t, r = new Array();
|
||||
r[0] = this.s;
|
||||
var p = this.DB-(i*this.DB)%8, d, k = 0;
|
||||
if(i-- > 0) {
|
||||
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
|
||||
r[k++] = d|(this.s<<(this.DB-p));
|
||||
while(i >= 0) {
|
||||
if(p < 8) {
|
||||
d = (this[i]&((1<<p)-1))<<(8-p);
|
||||
d |= this[--i]>>(p+=this.DB-8);
|
||||
}
|
||||
else {
|
||||
d = (this[i]>>(p-=8))&0xff;
|
||||
if(p <= 0) { p += this.DB; --i; }
|
||||
}
|
||||
if((d&0x80) != 0) d |= -256;
|
||||
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
|
||||
if(k > 0 || d != this.s) r[k++] = d;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function bnEquals(a) { return(this.compareTo(a)==0); }
|
||||
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
|
||||
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
|
||||
|
||||
// (protected) r = this op a (bitwise)
|
||||
function bnpBitwiseTo(a,op,r) {
|
||||
var i, f, m = Math.min(a.t,this.t);
|
||||
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
|
||||
if(a.t < this.t) {
|
||||
f = a.s&this.DM;
|
||||
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
|
||||
r.t = this.t;
|
||||
}
|
||||
else {
|
||||
f = this.s&this.DM;
|
||||
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
|
||||
r.t = a.t;
|
||||
}
|
||||
r.s = op(this.s,a.s);
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (public) this & a
|
||||
function op_and(x,y) { return x&y; }
|
||||
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
|
||||
|
||||
// (public) this | a
|
||||
function op_or(x,y) { return x|y; }
|
||||
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
|
||||
|
||||
// (public) this ^ a
|
||||
function op_xor(x,y) { return x^y; }
|
||||
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
|
||||
|
||||
// (public) this & ~a
|
||||
function op_andnot(x,y) { return x&~y; }
|
||||
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
|
||||
|
||||
// (public) ~this
|
||||
function bnNot() {
|
||||
var r = nbi();
|
||||
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
|
||||
r.t = this.t;
|
||||
r.s = ~this.s;
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) this << n
|
||||
function bnShiftLeft(n) {
|
||||
var r = nbi();
|
||||
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) this >> n
|
||||
function bnShiftRight(n) {
|
||||
var r = nbi();
|
||||
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// return index of lowest 1-bit in x, x < 2^31
|
||||
function lbit(x) {
|
||||
if(x == 0) return -1;
|
||||
var r = 0;
|
||||
if((x&0xffff) == 0) { x >>= 16; r += 16; }
|
||||
if((x&0xff) == 0) { x >>= 8; r += 8; }
|
||||
if((x&0xf) == 0) { x >>= 4; r += 4; }
|
||||
if((x&3) == 0) { x >>= 2; r += 2; }
|
||||
if((x&1) == 0) ++r;
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) returns index of lowest 1-bit (or -1 if none)
|
||||
function bnGetLowestSetBit() {
|
||||
for(var i = 0; i < this.t; ++i)
|
||||
if(this[i] != 0) return i*this.DB+lbit(this[i]);
|
||||
if(this.s < 0) return this.t*this.DB;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return number of 1 bits in x
|
||||
function cbit(x) {
|
||||
var r = 0;
|
||||
while(x != 0) { x &= x-1; ++r; }
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) return number of set bits
|
||||
function bnBitCount() {
|
||||
var r = 0, x = this.s&this.DM;
|
||||
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) true iff nth bit is set
|
||||
function bnTestBit(n) {
|
||||
var j = Math.floor(n/this.DB);
|
||||
if(j >= this.t) return(this.s!=0);
|
||||
return((this[j]&(1<<(n%this.DB)))!=0);
|
||||
}
|
||||
|
||||
// (protected) this op (1<<n)
|
||||
function bnpChangeBit(n,op) {
|
||||
var r = BigInteger.ONE.shiftLeft(n);
|
||||
this.bitwiseTo(r,op,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) this | (1<<n)
|
||||
function bnSetBit(n) { return this.changeBit(n,op_or); }
|
||||
|
||||
// (public) this & ~(1<<n)
|
||||
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
|
||||
|
||||
// (public) this ^ (1<<n)
|
||||
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
|
||||
|
||||
// (protected) r = this + a
|
||||
function bnpAddTo(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 > 0) r[i++] = c;
|
||||
else if(c < -1) r[i++] = this.DV+c;
|
||||
r.t = i;
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (public) this + a
|
||||
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
|
||||
|
||||
// (public) this - a
|
||||
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
|
||||
|
||||
// (public) this * a
|
||||
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
|
||||
|
||||
// (public) this^2
|
||||
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
|
||||
|
||||
// (public) this / a
|
||||
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
|
||||
|
||||
// (public) this % a
|
||||
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
|
||||
|
||||
// (public) [this/a,this%a]
|
||||
function bnDivideAndRemainder(a) {
|
||||
var q = nbi(), r = nbi();
|
||||
this.divRemTo(a,q,r);
|
||||
return new Array(q,r);
|
||||
}
|
||||
|
||||
// (protected) this *= n, this >= 0, 1 < n < DV
|
||||
function bnpDMultiply(n) {
|
||||
this[this.t] = this.am(0,n-1,this,0,0,this.t);
|
||||
++this.t;
|
||||
this.clamp();
|
||||
}
|
||||
|
||||
// (protected) this += n << w words, this >= 0
|
||||
function bnpDAddOffset(n,w) {
|
||||
if(n == 0) return;
|
||||
while(this.t <= w) this[this.t++] = 0;
|
||||
this[w] += n;
|
||||
while(this[w] >= this.DV) {
|
||||
this[w] -= this.DV;
|
||||
if(++w >= this.t) this[this.t++] = 0;
|
||||
++this[w];
|
||||
}
|
||||
}
|
||||
|
||||
// A "null" reducer
|
||||
function NullExp() {}
|
||||
function nNop(x) { return x; }
|
||||
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
|
||||
function nSqrTo(x,r) { x.squareTo(r); }
|
||||
|
||||
NullExp.prototype.convert = nNop;
|
||||
NullExp.prototype.revert = nNop;
|
||||
NullExp.prototype.mulTo = nMulTo;
|
||||
NullExp.prototype.sqrTo = nSqrTo;
|
||||
|
||||
// (public) this^e
|
||||
function bnPow(e) { return this.exp(e,new NullExp()); }
|
||||
|
||||
// (protected) r = lower n words of "this * a", a.t <= n
|
||||
// "this" should be the larger one if appropriate.
|
||||
function bnpMultiplyLowerTo(a,n,r) {
|
||||
var i = Math.min(this.t+a.t,n);
|
||||
r.s = 0; // assumes a,this >= 0
|
||||
r.t = i;
|
||||
while(i > 0) r[--i] = 0;
|
||||
var j;
|
||||
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
|
||||
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
|
||||
r.clamp();
|
||||
}
|
||||
|
||||
// (protected) r = "this * a" without lower n words, n > 0
|
||||
// "this" should be the larger one if appropriate.
|
||||
function bnpMultiplyUpperTo(a,n,r) {
|
||||
--n;
|
||||
var i = r.t = this.t+a.t-n;
|
||||
r.s = 0; // assumes a,this >= 0
|
||||
while(--i >= 0) r[i] = 0;
|
||||
for(i = Math.max(n-this.t,0); i < a.t; ++i)
|
||||
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
|
||||
r.clamp();
|
||||
r.drShiftTo(1,r);
|
||||
}
|
||||
|
||||
// Barrett modular reduction
|
||||
function Barrett(m) {
|
||||
// setup Barrett
|
||||
this.r2 = nbi();
|
||||
this.q3 = nbi();
|
||||
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
|
||||
this.mu = this.r2.divide(m);
|
||||
this.m = m;
|
||||
}
|
||||
|
||||
function barrettConvert(x) {
|
||||
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
|
||||
else if(x.compareTo(this.m) < 0) return x;
|
||||
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
|
||||
}
|
||||
|
||||
function barrettRevert(x) { return x; }
|
||||
|
||||
// x = x mod m (HAC 14.42)
|
||||
function barrettReduce(x) {
|
||||
x.drShiftTo(this.m.t-1,this.r2);
|
||||
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
|
||||
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
|
||||
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
|
||||
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
|
||||
x.subTo(this.r2,x);
|
||||
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
||||
}
|
||||
|
||||
// r = x^2 mod m; x != r
|
||||
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
||||
|
||||
// r = x*y mod m; x,y != r
|
||||
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
||||
|
||||
Barrett.prototype.convert = barrettConvert;
|
||||
Barrett.prototype.revert = barrettRevert;
|
||||
Barrett.prototype.reduce = barrettReduce;
|
||||
Barrett.prototype.mulTo = barrettMulTo;
|
||||
Barrett.prototype.sqrTo = barrettSqrTo;
|
||||
|
||||
// (public) this^e % m (HAC 14.85)
|
||||
function bnModPow(e,m) {
|
||||
var i = e.bitLength(), k, r = nbv(1), z;
|
||||
if(i <= 0) return r;
|
||||
else if(i < 18) k = 1;
|
||||
else if(i < 48) k = 3;
|
||||
else if(i < 144) k = 4;
|
||||
else if(i < 768) k = 5;
|
||||
else k = 6;
|
||||
if(i < 8)
|
||||
z = new Classic(m);
|
||||
else if(m.isEven())
|
||||
z = new Barrett(m);
|
||||
else
|
||||
z = new Montgomery(m);
|
||||
|
||||
// precomputation
|
||||
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
|
||||
g[1] = z.convert(this);
|
||||
if(k > 1) {
|
||||
var g2 = nbi();
|
||||
z.sqrTo(g[1],g2);
|
||||
while(n <= km) {
|
||||
g[n] = nbi();
|
||||
z.mulTo(g2,g[n-2],g[n]);
|
||||
n += 2;
|
||||
}
|
||||
}
|
||||
|
||||
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
|
||||
i = nbits(e[j])-1;
|
||||
while(j >= 0) {
|
||||
if(i >= k1) w = (e[j]>>(i-k1))&km;
|
||||
else {
|
||||
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
|
||||
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
|
||||
}
|
||||
|
||||
n = k;
|
||||
while((w&1) == 0) { w >>= 1; --n; }
|
||||
if((i -= n) < 0) { i += this.DB; --j; }
|
||||
if(is1) { // ret == 1, don't bother squaring or multiplying it
|
||||
g[w].copyTo(r);
|
||||
is1 = false;
|
||||
}
|
||||
else {
|
||||
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
|
||||
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
|
||||
z.mulTo(r2,g[w],r);
|
||||
}
|
||||
|
||||
while(j >= 0 && (e[j]&(1<<i)) == 0) {
|
||||
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
|
||||
if(--i < 0) { i = this.DB-1; --j; }
|
||||
}
|
||||
}
|
||||
return z.revert(r);
|
||||
}
|
||||
|
||||
// (public) gcd(this,a) (HAC 14.54)
|
||||
function bnGCD(a) {
|
||||
var x = (this.s<0)?this.negate():this.clone();
|
||||
var y = (a.s<0)?a.negate():a.clone();
|
||||
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
|
||||
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
|
||||
if(g < 0) return x;
|
||||
if(i < g) g = i;
|
||||
if(g > 0) {
|
||||
x.rShiftTo(g,x);
|
||||
y.rShiftTo(g,y);
|
||||
}
|
||||
while(x.signum() > 0) {
|
||||
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
|
||||
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
|
||||
if(x.compareTo(y) >= 0) {
|
||||
x.subTo(y,x);
|
||||
x.rShiftTo(1,x);
|
||||
}
|
||||
else {
|
||||
y.subTo(x,y);
|
||||
y.rShiftTo(1,y);
|
||||
}
|
||||
}
|
||||
if(g > 0) y.lShiftTo(g,y);
|
||||
return y;
|
||||
}
|
||||
|
||||
// (protected) this % n, n < 2^26
|
||||
function bnpModInt(n) {
|
||||
if(n <= 0) return 0;
|
||||
var d = this.DV%n, r = (this.s<0)?n-1:0;
|
||||
if(this.t > 0)
|
||||
if(d == 0) r = this[0]%n;
|
||||
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
|
||||
return r;
|
||||
}
|
||||
|
||||
// (public) 1/this % m (HAC 14.61)
|
||||
function bnModInverse(m) {
|
||||
var ac = m.isEven();
|
||||
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
|
||||
var u = m.clone(), v = this.clone();
|
||||
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
|
||||
while(u.signum() != 0) {
|
||||
while(u.isEven()) {
|
||||
u.rShiftTo(1,u);
|
||||
if(ac) {
|
||||
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
|
||||
a.rShiftTo(1,a);
|
||||
}
|
||||
else if(!b.isEven()) b.subTo(m,b);
|
||||
b.rShiftTo(1,b);
|
||||
}
|
||||
while(v.isEven()) {
|
||||
v.rShiftTo(1,v);
|
||||
if(ac) {
|
||||
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
|
||||
c.rShiftTo(1,c);
|
||||
}
|
||||
else if(!d.isEven()) d.subTo(m,d);
|
||||
d.rShiftTo(1,d);
|
||||
}
|
||||
if(u.compareTo(v) >= 0) {
|
||||
u.subTo(v,u);
|
||||
if(ac) a.subTo(c,a);
|
||||
b.subTo(d,b);
|
||||
}
|
||||
else {
|
||||
v.subTo(u,v);
|
||||
if(ac) c.subTo(a,c);
|
||||
d.subTo(b,d);
|
||||
}
|
||||
}
|
||||
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
|
||||
if(d.compareTo(m) >= 0) return d.subtract(m);
|
||||
if(d.signum() < 0) d.addTo(m,d); else return d;
|
||||
if(d.signum() < 0) return d.add(m); else return d;
|
||||
}
|
||||
|
||||
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
|
||||
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
|
||||
|
||||
// (public) test primality with certainty >= 1-.5^t
|
||||
function bnIsProbablePrime(t) {
|
||||
var i, x = this.abs();
|
||||
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
|
||||
for(i = 0; i < lowprimes.length; ++i)
|
||||
if(x[0] == lowprimes[i]) return true;
|
||||
return false;
|
||||
}
|
||||
if(x.isEven()) return false;
|
||||
i = 1;
|
||||
while(i < lowprimes.length) {
|
||||
var m = lowprimes[i], j = i+1;
|
||||
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
|
||||
m = x.modInt(m);
|
||||
while(i < j) if(m%lowprimes[i++] == 0) return false;
|
||||
}
|
||||
return x.millerRabin(t);
|
||||
}
|
||||
|
||||
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
||||
function bnpMillerRabin(t) {
|
||||
var n1 = this.subtract(BigInteger.ONE);
|
||||
var k = n1.getLowestSetBit();
|
||||
if(k <= 0) return false;
|
||||
var r = n1.shiftRight(k);
|
||||
t = (t+1)>>1;
|
||||
if(t > lowprimes.length) t = lowprimes.length;
|
||||
var a = nbi();
|
||||
for(var i = 0; i < t; ++i) {
|
||||
//Pick bases at random, instead of starting at 2
|
||||
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
|
||||
var y = a.modPow(r,this);
|
||||
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
|
||||
var j = 1;
|
||||
while(j++ < k && y.compareTo(n1) != 0) {
|
||||
y = y.modPowInt(2,this);
|
||||
if(y.compareTo(BigInteger.ONE) == 0) return false;
|
||||
}
|
||||
if(y.compareTo(n1) != 0) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// protected
|
||||
BigInteger.prototype.chunkSize = bnpChunkSize;
|
||||
BigInteger.prototype.toRadix = bnpToRadix;
|
||||
BigInteger.prototype.fromRadix = bnpFromRadix;
|
||||
BigInteger.prototype.fromNumber = bnpFromNumber;
|
||||
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
|
||||
BigInteger.prototype.changeBit = bnpChangeBit;
|
||||
BigInteger.prototype.addTo = bnpAddTo;
|
||||
BigInteger.prototype.dMultiply = bnpDMultiply;
|
||||
BigInteger.prototype.dAddOffset = bnpDAddOffset;
|
||||
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
|
||||
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
|
||||
BigInteger.prototype.modInt = bnpModInt;
|
||||
BigInteger.prototype.millerRabin = bnpMillerRabin;
|
||||
|
||||
// public
|
||||
BigInteger.prototype.clone = bnClone;
|
||||
BigInteger.prototype.intValue = bnIntValue;
|
||||
BigInteger.prototype.byteValue = bnByteValue;
|
||||
BigInteger.prototype.shortValue = bnShortValue;
|
||||
BigInteger.prototype.signum = bnSigNum;
|
||||
BigInteger.prototype.toByteArray = bnToByteArray;
|
||||
BigInteger.prototype.equals = bnEquals;
|
||||
BigInteger.prototype.min = bnMin;
|
||||
BigInteger.prototype.max = bnMax;
|
||||
BigInteger.prototype.and = bnAnd;
|
||||
BigInteger.prototype.or = bnOr;
|
||||
BigInteger.prototype.xor = bnXor;
|
||||
BigInteger.prototype.andNot = bnAndNot;
|
||||
BigInteger.prototype.not = bnNot;
|
||||
BigInteger.prototype.shiftLeft = bnShiftLeft;
|
||||
BigInteger.prototype.shiftRight = bnShiftRight;
|
||||
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
|
||||
BigInteger.prototype.bitCount = bnBitCount;
|
||||
BigInteger.prototype.testBit = bnTestBit;
|
||||
BigInteger.prototype.setBit = bnSetBit;
|
||||
BigInteger.prototype.clearBit = bnClearBit;
|
||||
BigInteger.prototype.flipBit = bnFlipBit;
|
||||
BigInteger.prototype.add = bnAdd;
|
||||
BigInteger.prototype.subtract = bnSubtract;
|
||||
BigInteger.prototype.multiply = bnMultiply;
|
||||
BigInteger.prototype.divide = bnDivide;
|
||||
BigInteger.prototype.remainder = bnRemainder;
|
||||
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
|
||||
BigInteger.prototype.modPow = bnModPow;
|
||||
BigInteger.prototype.modInverse = bnModInverse;
|
||||
BigInteger.prototype.pow = bnPow;
|
||||
BigInteger.prototype.gcd = bnGCD;
|
||||
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
|
||||
|
||||
// JSBN-specific extension
|
||||
BigInteger.prototype.square = bnSquare;
|
||||
|
||||
// BigInteger interfaces not implemented in jsbn:
|
||||
|
||||
// BigInteger(int signum, byte[] magnitude)
|
||||
// double doubleValue()
|
||||
// float floatValue()
|
||||
// int hashCode()
|
||||
// long longValue()
|
||||
// static BigInteger valueOf(long val)
|
||||
235
js/remote.js
235
js/remote.js
@@ -12,18 +12,25 @@ var util = require('util');
|
||||
var WebSocket = require('ws');
|
||||
|
||||
// --> trusted: truthy, if remote is trusted
|
||||
var Remote = function (trusted, websocket_ip, websocket_port, trace) {
|
||||
var Remote = function (trusted, websocket_ip, websocket_port, config, trace) {
|
||||
this.trusted = trusted;
|
||||
this.websocket_ip = websocket_ip;
|
||||
this.websocket_port = websocket_port;
|
||||
this.id = 0;
|
||||
this.config = config;
|
||||
this.trace = trace;
|
||||
this.ledger_closed = undefined;
|
||||
this.ledger_current_index = undefined;
|
||||
this.stand_alone = undefined;
|
||||
|
||||
// Cache information for accounts.
|
||||
this.account = {};
|
||||
this.accounts = {
|
||||
// Consider sequence numbers stable if you know you're not generating bad transactions.
|
||||
// Otherwise, clear it to have it automatically refreshed from the network.
|
||||
|
||||
// account : { seq : __ }
|
||||
|
||||
};
|
||||
|
||||
// Cache for various ledgers.
|
||||
// XXX Clear when ledger advances.
|
||||
@@ -34,7 +41,18 @@ var Remote = function (trusted, websocket_ip, websocket_port, trace) {
|
||||
|
||||
var remoteConfig = function (config, server, trace) {
|
||||
var serverConfig = config.servers[server];
|
||||
return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, trace);
|
||||
return new Remote(serverConfig.trusted, serverConfig.websocket_ip, serverConfig.websocket_port, config, trace);
|
||||
};
|
||||
|
||||
var flags = {
|
||||
// OfferCreate flags:
|
||||
'tfPassive' : 0x00010000,
|
||||
|
||||
// Payment flags:
|
||||
'tfCreateAccount' : 0x00010000,
|
||||
'tfPartialPayment' : 0x00020000,
|
||||
'tfLimitQuality' : 0x00040000,
|
||||
'tfNoRippleDirect' : 0x00080000,
|
||||
};
|
||||
|
||||
// XXX This needs to be determined from the network.
|
||||
@@ -45,15 +63,7 @@ var fees = {
|
||||
'offer' : 100,
|
||||
};
|
||||
|
||||
// For accounts we cache things like sequence numbers.
|
||||
var accounts = {
|
||||
// Consider sequence numbers stable if you know you're not generating bad transactions.
|
||||
// Otherwise, clear it to have it automatically refreshed from the network.
|
||||
|
||||
// acount : { seq : __ }
|
||||
};
|
||||
|
||||
Remote.method('connect_helper', function () {
|
||||
Remote.prototype.connect_helper = function () {
|
||||
var self = this;
|
||||
|
||||
if (this.trace) console.log("remote: connect: %s", this.url);
|
||||
@@ -78,11 +88,13 @@ Remote.method('connect_helper', function () {
|
||||
|
||||
if (self.expire) {
|
||||
if (this.trace) console.log("remote: was expired");
|
||||
|
||||
self.done(ws.readyState);
|
||||
} else {
|
||||
// Delay and retry.
|
||||
setTimeout(function () {
|
||||
if (this.trace) console.log("remote: retry");
|
||||
|
||||
self.connect_helper();
|
||||
}, 50); // Retry rate 50ms.
|
||||
}
|
||||
@@ -91,6 +103,7 @@ Remote.method('connect_helper', function () {
|
||||
// Covers failure to open.
|
||||
ws.onclose = function () {
|
||||
if (this.trace) console.log("remote: onclose: %s", ws.readyState);
|
||||
|
||||
ws.onerror = undefined;
|
||||
self.done(ws.readyState);
|
||||
};
|
||||
@@ -102,6 +115,7 @@ Remote.method('connect_helper', function () {
|
||||
|
||||
if (message.type !== 'response') {
|
||||
console.log("unexpected message: %s", json);
|
||||
|
||||
} else {
|
||||
var done = ws.response[message.id];
|
||||
if (done) {
|
||||
@@ -111,12 +125,12 @@ Remote.method('connect_helper', function () {
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Target state is connectted.
|
||||
// done(readyState):
|
||||
// --> readyState: OPEN, CLOSED
|
||||
Remote.method('connect', function (done, timeout) {
|
||||
Remote.prototype.connect = function (done, timeout) {
|
||||
var self = this;
|
||||
|
||||
this.url = util.format("ws://%s:%s", this.websocket_ip, this.websocket_port);
|
||||
@@ -128,7 +142,7 @@ Remote.method('connect', function (done, timeout) {
|
||||
this.expire = false;
|
||||
|
||||
setTimeout(function () {
|
||||
if (this.trace) console.log("remote: expire: timeout");
|
||||
if (self.trace) console.log("remote: expire: timeout");
|
||||
self.expire = true;
|
||||
}, timeout);
|
||||
} else {
|
||||
@@ -137,31 +151,32 @@ Remote.method('connect', function (done, timeout) {
|
||||
}
|
||||
|
||||
this.connect_helper();
|
||||
});
|
||||
};
|
||||
|
||||
// Target stated is disconnected.
|
||||
Remote.method('disconnect', function (done) {
|
||||
var ws = this.ws;
|
||||
Remote.prototype.disconnect = function (done) {
|
||||
var self = this;
|
||||
var ws = this.ws;
|
||||
|
||||
ws.onclose = function () {
|
||||
if (this.trace) console.log("remote: onclose: %s", ws.readyState);
|
||||
if (self.trace) console.log("remote: onclose: %s", ws.readyState);
|
||||
done(ws.readyState);
|
||||
};
|
||||
|
||||
ws.close();
|
||||
});
|
||||
};
|
||||
|
||||
// Send a request. The request should lack the id.
|
||||
// <-> request: what to send, consumed.
|
||||
Remote.prototype.request = function (request, onDone, onFailure) {
|
||||
var self = this;
|
||||
|
||||
// Send a command. The comman should lack the id.
|
||||
// <-> command: what to send, consumed.
|
||||
Remote.method('request', function (request, onDone, onFailure) {
|
||||
this.id += 1; // Advance id.
|
||||
|
||||
var ws = this.ws;
|
||||
|
||||
request.id = this.id;
|
||||
|
||||
ws.response[request.id] = function (response) {
|
||||
if (this.trace) console.log("remote: response: %s", JSON.stringify(response));
|
||||
this.ws.response[request.id] = function (response) {
|
||||
if (self.trace) console.log("remote: response: %s", JSON.stringify(response));
|
||||
|
||||
if (onFailure && response.error)
|
||||
{
|
||||
@@ -175,25 +190,27 @@ Remote.method('request', function (request, onDone, onFailure) {
|
||||
|
||||
if (this.trace) console.log("remote: request: %s", JSON.stringify(request));
|
||||
|
||||
ws.send(JSON.stringify(request));
|
||||
});
|
||||
this.ws.send(JSON.stringify(request));
|
||||
};
|
||||
|
||||
Remote.method('request_ledger_closed', function (onDone, onFailure) {
|
||||
Remote.prototype.request_ledger_closed = function (onDone, onFailure) {
|
||||
assert(this.trusted); // If not trusted, need to check proof.
|
||||
this.request({ 'command' : 'ledger_closed' }, onDone, onFailure);
|
||||
});
|
||||
};
|
||||
|
||||
// Get the current proposed ledger entry. May be closed (and revised) at any time (even before returning).
|
||||
// Only for use by unit tests.
|
||||
Remote.method('request_ledger_current', function (onDone, onFailure) {
|
||||
Remote.prototype.request_ledger_current = function (onDone, onFailure) {
|
||||
this.request({ 'command' : 'ledger_current' }, onDone, onFailure);
|
||||
});
|
||||
};
|
||||
|
||||
// <-> request:
|
||||
// --> ledger : optional
|
||||
// --> ledger_index : optional
|
||||
// --> type
|
||||
Remote.method('request_ledger_entry', function (req, onDone, onFailure) {
|
||||
Remote.prototype.request_ledger_entry = function (req, onDone, onFailure) {
|
||||
var self = this;
|
||||
|
||||
assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol.
|
||||
|
||||
req.command = 'ledger_entry';
|
||||
@@ -203,7 +220,8 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) {
|
||||
// XXX Initial implementation no caching.
|
||||
this.request(req, onDone, onFailure);
|
||||
}
|
||||
else if (req.ledger_index)
|
||||
// else if (req.ledger_index)
|
||||
else
|
||||
{
|
||||
// Current
|
||||
// XXX Only allow with standalone mode. Must sync response with advance.
|
||||
@@ -218,7 +236,7 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) {
|
||||
cache = this.ledgers.current.account_root = {};
|
||||
}
|
||||
|
||||
var entry = this.ledgers.current.account_root[req.account];
|
||||
entry = this.ledgers.current.account_root[req.account];
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -235,32 +253,32 @@ Remote.method('request_ledger_entry', function (req, onDone, onFailure) {
|
||||
|
||||
// Submit request
|
||||
this.request(req, function (r) {
|
||||
// Got result.
|
||||
switch (req.type) {
|
||||
case 'account_root':
|
||||
this.ledgers.current.account_root.account = r;
|
||||
break;
|
||||
|
||||
default:
|
||||
// This type not cached.
|
||||
}
|
||||
onDone(r);
|
||||
}, onFailure);
|
||||
// Got result.
|
||||
switch (req.type) {
|
||||
case 'account_root':
|
||||
self.ledgers.current.account_root[r.node.Account] = r.node;
|
||||
break;
|
||||
|
||||
default:
|
||||
// This type not cached.
|
||||
// nothing();
|
||||
break;
|
||||
}
|
||||
onDone(r.node);
|
||||
}, onFailure);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Submit a json transaction.
|
||||
// done(value)
|
||||
// <-> value: { 'status', status, 'result' : result, ... }
|
||||
// done may be called up to 3 times.
|
||||
Remote.method('submit', function (json, private_key, onDone, onFailure) {
|
||||
var req = {};
|
||||
|
||||
// XXX <-> value: { 'status', status, 'result' : result, ... }
|
||||
Remote.prototype.submit = function (req, onDone, onFailure) {
|
||||
if (this.trace) console.log("remote: submit: %s", JSON.stringify(req));
|
||||
|
||||
req.command = 'submit';
|
||||
req.json = json;
|
||||
|
||||
if (private_key && !this.trusted)
|
||||
if (req.secret && !this.trusted)
|
||||
{
|
||||
onFailure({ 'error' : 'untrustedSever', 'request' : req });
|
||||
}
|
||||
@@ -268,7 +286,7 @@ Remote.method('submit', function (json, private_key, onDone, onFailure) {
|
||||
{
|
||||
this.request(req, onDone, onFailure);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// Higher level functions.
|
||||
@@ -276,54 +294,123 @@ Remote.method('submit', function (json, private_key, onDone, onFailure) {
|
||||
|
||||
// Subscribe to a server to get the current and closed ledger.
|
||||
// XXX Set up routine to update on notification.
|
||||
Remote.method('server_subscribe', function (onDone, onFailure) {
|
||||
Remote.prototype.server_subscribe = function (onDone, onFailure) {
|
||||
var self = this;
|
||||
|
||||
this.request(
|
||||
{ 'command' : 'server_subscribe' },
|
||||
function (r) {
|
||||
this.ledger_current_index = r.ledger_current_index;
|
||||
this.ledger_closed = r.ledger_closed;
|
||||
this.stand_alone = r.stand_alone;
|
||||
onDone();
|
||||
function (r) {
|
||||
self.ledger_current_index = r.ledger_current_index;
|
||||
self.ledger_closed = r.ledger_closed;
|
||||
self.stand_alone = r.stand_alone;
|
||||
onDone();
|
||||
},
|
||||
onFailure
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// Refresh accounts[account].seq
|
||||
// done(result);
|
||||
Remote.method('account_seq', function (account, onDone, onFailure) {
|
||||
Remote.prototype.account_seq = function (account, advance, onDone, onFailure) {
|
||||
var self = this;
|
||||
var account_root_entry = this.accounts[account];
|
||||
|
||||
if (account_root_entry && account_root_entry.seq)
|
||||
{
|
||||
onDone(account_root_entry.seq);
|
||||
var seq = account_root_entry.seq;
|
||||
|
||||
if (advance) account_root_entry.seq += 1;
|
||||
|
||||
onDone(seq);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to get the ledger entry.
|
||||
this.request_ledger_entry(
|
||||
{
|
||||
'ledger' : this.ledger_closed,
|
||||
'account_root' : account
|
||||
'ledger' : this.ledger_closed,
|
||||
'type' : 'account_root',
|
||||
'account_root' : account
|
||||
},
|
||||
function (r) {
|
||||
function (node) {
|
||||
// Extract the seqence number from the account root entry.
|
||||
this.accounts[account].seq = r.seq;
|
||||
onDone(r.seq);
|
||||
var seq = node.Sequence;
|
||||
|
||||
if (!account_root_entry) self.accounts[account] = {};
|
||||
|
||||
self.accounts[account].seq = seq + !!advance;
|
||||
|
||||
onDone(seq);
|
||||
},
|
||||
onFailure
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// A submit that fills in the sequence number.
|
||||
Remote.method('submit_seq', function (onDone, onFailure) {
|
||||
Remote.prototype.submit_seq = function (trans, onDirty, onDone, onFailure) {
|
||||
var self = this;
|
||||
|
||||
});
|
||||
// Get the next sequence number for the account.
|
||||
this.account_seq(trans.transaction.Account, true,
|
||||
function (seq) {
|
||||
trans.transaction.Sequence = seq;
|
||||
self.submit(trans, onDone, onFailure);
|
||||
},
|
||||
onFailure);
|
||||
};
|
||||
|
||||
// Mark an account's root node as dirty.
|
||||
Remote.prototype.dirty_account_root = function (account) {
|
||||
delete this.ledgers.current.account_root.account;
|
||||
};
|
||||
|
||||
//
|
||||
// Transactions
|
||||
//
|
||||
|
||||
Remote.prototype.ripple_line_set = function (secret, src, dst, amount, 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;
|
||||
|
||||
this.submit_seq(
|
||||
{
|
||||
'transaction' : {
|
||||
'TransactionType' : 'CreditSet',
|
||||
'Account' : src_account,
|
||||
'Destination' : dst_account,
|
||||
'Fee' : create ? fees.account_create : fees['default'],
|
||||
'Amount' : amount,
|
||||
},
|
||||
'secret' : secret,
|
||||
}, function () {
|
||||
}, onDone);
|
||||
};
|
||||
|
||||
Remote.prototype.send_xns = function (secret, src, dst, amount, 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;
|
||||
|
||||
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,
|
||||
},
|
||||
'secret' : secret,
|
||||
}, function () {
|
||||
}, onDone);
|
||||
};
|
||||
|
||||
exports.Remote = Remote;
|
||||
exports.remoteConfig = remoteConfig;
|
||||
exports.fees = fees;
|
||||
exports.accounts = accounts;
|
||||
exports.flags = flags;
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
|
||||
1
js/sjcl
Submodule
1
js/sjcl
Submodule
Submodule js/sjcl added at d04d0bdccd
198
js/utils.js
198
js/utils.js
@@ -4,127 +4,151 @@ var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
Function.prototype.method = function(name,func) {
|
||||
this.prototype[name] = func;
|
||||
this.prototype[name] = func;
|
||||
|
||||
return this;
|
||||
return this;
|
||||
};
|
||||
|
||||
var filterErr = function(code, done) {
|
||||
return function(e) {
|
||||
done(e.code !== code ? e : undefined);
|
||||
};
|
||||
return function(e) {
|
||||
done(e.code !== code ? e : undefined);
|
||||
};
|
||||
};
|
||||
|
||||
var throwErr = function(done) {
|
||||
return function(e) {
|
||||
if (e)
|
||||
throw e;
|
||||
|
||||
done();
|
||||
};
|
||||
return function(e) {
|
||||
if (e)
|
||||
throw e;
|
||||
|
||||
done();
|
||||
};
|
||||
};
|
||||
|
||||
// apply function to elements of array. Return first true value to done or undefined.
|
||||
var mapOr = function(func, array, done) {
|
||||
if (array.length) {
|
||||
func(array[array.length-1], function(v) {
|
||||
if (v) {
|
||||
done(v);
|
||||
}
|
||||
else {
|
||||
array.length -= 1;
|
||||
mapOr(func, array, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
done();
|
||||
}
|
||||
if (array.length) {
|
||||
func(array[array.length-1], function(v) {
|
||||
if (v) {
|
||||
done(v);
|
||||
}
|
||||
else {
|
||||
array.length -= 1;
|
||||
mapOr(func, array, done);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
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.
|
||||
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);
|
||||
}
|
||||
});
|
||||
mkPath(path.dirname(dirPath), mode, function(e) {
|
||||
if (e) {
|
||||
throw e;
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
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);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
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);
|
||||
}
|
||||
});
|
||||
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);
|
||||
func(arguments);
|
||||
};
|
||||
return function() {
|
||||
console.log("%s: %s", trace, arguments.toString);
|
||||
func(arguments);
|
||||
};
|
||||
};
|
||||
|
||||
var hexToString = function (h) {
|
||||
var a = [];
|
||||
var i = 0;
|
||||
|
||||
if (h.length % 2) {
|
||||
a.push(String.fromCharCode(parseInt(h.substring(0, 1), 16)));
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for (; i != h.length; i += 2) {
|
||||
a.push(String.fromCharCode(parseInt(h.substring(i, i+2), 16)));
|
||||
}
|
||||
|
||||
return a.join("");
|
||||
};
|
||||
|
||||
var stringToHex = function (s) {
|
||||
return Array.prototype.map.call(s, function (c) {
|
||||
var b = c.charCodeAt(0);
|
||||
|
||||
return b < 16 ? "0" + b.toString(16) : b.toString(16);
|
||||
}).join("");
|
||||
};
|
||||
|
||||
exports.emptyPath = emptyPath;
|
||||
@@ -133,5 +157,7 @@ exports.mkPath = mkPath;
|
||||
exports.resetPath = resetPath;
|
||||
exports.rmPath = rmPath;
|
||||
exports.trace = trace;
|
||||
exports.hexToString = hexToString;
|
||||
exports.stringToHex = stringToHex;
|
||||
|
||||
// vim:ts=4
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
|
||||
@@ -18,6 +18,7 @@ SField sfLedgerEntry(STI_LEDGERENTRY, 1, "LedgerEntry");
|
||||
SField sfTransaction(STI_TRANSACTION, 1, "Transaction");
|
||||
SField sfValidation(STI_VALIDATION, 1, "Validation");
|
||||
SField sfID(STI_HASH256, 257, "id");
|
||||
SField sfIndex(STI_HASH256, 258, "index");
|
||||
|
||||
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
|
||||
#define TYPE(name, type, index)
|
||||
@@ -26,6 +27,12 @@ SField sfID(STI_HASH256, 257, "id");
|
||||
#undef TYPE
|
||||
|
||||
|
||||
SField::SField(SerializedTypeID tid, int fv) : fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv)
|
||||
{ // call with the map mutex
|
||||
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv);
|
||||
codeToField[fieldCode] = this;
|
||||
}
|
||||
|
||||
SField::ref SField::getField(int code)
|
||||
{
|
||||
int type = code >> 16;
|
||||
@@ -33,16 +40,18 @@ SField::ref SField::getField(int code)
|
||||
|
||||
if ((type <= 0) || (field <= 0))
|
||||
return sfInvalid;
|
||||
{ //JED: Did this to fix a deadlock. david you should check. Line after this block also has a scoped lock
|
||||
// why doe sthis thing even need a mutex?
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
|
||||
std::map<int, SField::ptr>::iterator it = codeToField.find(code);
|
||||
if (it != codeToField.end())
|
||||
return *(it->second);
|
||||
boost::mutex::scoped_lock sl(mapMutex);
|
||||
|
||||
switch (type)
|
||||
{ // types we are willing to dynamically extend
|
||||
std::map<int, SField::ptr>::iterator it = codeToField.find(code);
|
||||
if (it != codeToField.end())
|
||||
return *(it->second);
|
||||
|
||||
if (field > 255) // don't dynamically extend types that have no binary encoding
|
||||
return sfInvalid;
|
||||
|
||||
switch (type)
|
||||
{ // types we are willing to dynamically extend
|
||||
|
||||
#define FIELD(name, type, index)
|
||||
#define TYPE(name, type, index) case STI_##type:
|
||||
@@ -51,14 +60,11 @@ SField::ref SField::getField(int code)
|
||||
#undef TYPE
|
||||
|
||||
break;
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
|
||||
}// end scope lock
|
||||
std::string dynName = lexical_cast_i(type) + "/" + lexical_cast_i(field);
|
||||
return *(new SField(code, static_cast<SerializedTypeID>(type), field, dynName.c_str()));
|
||||
return *(new SField(static_cast<SerializedTypeID>(type), field));
|
||||
}
|
||||
|
||||
int SField::compare(SField::ref f1, SField::ref f2)
|
||||
|
||||
@@ -43,6 +43,8 @@ protected:
|
||||
static std::map<int, ptr> codeToField;
|
||||
static boost::mutex mapMutex;
|
||||
|
||||
SField(SerializedTypeID id, int val);
|
||||
|
||||
public:
|
||||
|
||||
const int fieldCode; // (type<<16)|index
|
||||
@@ -80,6 +82,7 @@ public:
|
||||
bool isInvalid() const { return fieldCode == -1; }
|
||||
bool isKnown() const { return fieldType != STI_UNKNOWN; }
|
||||
bool isBinary() const { return fieldValue < 256; }
|
||||
bool isDiscardable() const { return fieldValue > 256; }
|
||||
|
||||
bool operator==(const SField& f) const { return fieldCode == f.fieldCode; }
|
||||
bool operator!=(const SField& f) const { return fieldCode != f.fieldCode; }
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
HashedObjectStore::HashedObjectStore(int cacheSize, int cacheAge) :
|
||||
mCache(cacheSize, cacheAge), mWritePending(false)
|
||||
{
|
||||
@@ -22,9 +24,7 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index,
|
||||
if (!theApp->getHashNodeDB()) return true;
|
||||
if (mCache.touch(hash))
|
||||
{
|
||||
#ifdef HS_DEBUG
|
||||
Log(lsTRACE) << "HOS: " << hash << " store: incache";
|
||||
#endif
|
||||
cLog(lsTRACE) << "HOS: " << hash << " store: incache";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ void HashedObjectStore::bulkWrite()
|
||||
mWriteSet.swap(set);
|
||||
mWritePending = false;
|
||||
}
|
||||
Log(lsINFO) << "HOS: BulkWrite " << set.size();
|
||||
cLog(lsINFO) << "HOS: BulkWrite " << set.size();
|
||||
|
||||
static boost::format fExists("SELECT ObjType FROM CommittedObjects WHERE Hash = '%s';");
|
||||
static boost::format
|
||||
@@ -94,7 +94,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash)
|
||||
obj = mCache.fetch(hash);
|
||||
if (obj)
|
||||
{
|
||||
Log(lsTRACE) << "HOS: " << hash << " fetch: incache";
|
||||
cLog(lsTRACE) << "HOS: " << hash << " fetch: incache";
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash)
|
||||
|
||||
if (!db->executeSQL(sql) || !db->startIterRows())
|
||||
{
|
||||
Log(lsTRACE) << "HOS: " << hash << " fetch: not in db";
|
||||
cLog(lsTRACE) << "HOS: " << hash << " fetch: not in db";
|
||||
return HashedObject::pointer();
|
||||
}
|
||||
|
||||
@@ -136,14 +136,14 @@ HashedObject::pointer HashedObjectStore::retrieve(const uint256& hash)
|
||||
case 'A': htype = hotACCOUNT_NODE; break;
|
||||
case 'N': htype = hotTRANSACTION_NODE; break;
|
||||
default:
|
||||
Log(lsERROR) << "Invalid hashed object";
|
||||
cLog(lsERROR) << "Invalid hashed object";
|
||||
return HashedObject::pointer();
|
||||
}
|
||||
|
||||
obj = boost::make_shared<HashedObject>(htype, index, data, hash);
|
||||
mCache.canonicalize(hash, obj);
|
||||
}
|
||||
Log(lsTRACE) << "HOS: " << hash << " fetch: in db";
|
||||
cLog(lsTRACE) << "HOS: " << hash << " fetch: in db";
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "HashPrefixes.h"
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(1),
|
||||
mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0),
|
||||
@@ -427,11 +428,13 @@ Ledger::pointer Ledger::getSQL(const std::string& sql,bool isMutable)
|
||||
closeFlags, closeResolution, ledgerSeq,isMutable));
|
||||
if (ret->getHash() != ledgerHash)
|
||||
{
|
||||
Json::StyledStreamWriter ssw;
|
||||
Log(lsERROR) << "Failed on ledger";
|
||||
Json::Value p;
|
||||
ret->addJson(p, LEDGER_JSON_FULL);
|
||||
ssw.write(Log(lsERROR).ref(), p);
|
||||
if (sLog(lsERROR))
|
||||
{
|
||||
Log(lsERROR) << "Failed on ledger";
|
||||
Json::Value p;
|
||||
ret->addJson(p, LEDGER_JSON_FULL);
|
||||
Log(lsERROR) << p;
|
||||
}
|
||||
assert(false);
|
||||
return Ledger::pointer();
|
||||
}
|
||||
|
||||
@@ -142,9 +142,8 @@ public:
|
||||
boost::posix_time::ptime getCloseTime() const;
|
||||
|
||||
// low level functions
|
||||
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
|
||||
SHAMap::pointer peekAccountStateMap() { return mAccountStateMap; }
|
||||
Ledger::pointer snapShot(bool isMutable);
|
||||
SHAMap::ref peekTransactionMap() { return mTransactionMap; }
|
||||
SHAMap::ref peekAccountStateMap() { return mAccountStateMap; }
|
||||
|
||||
// ledger sync functions
|
||||
void setAcquiring(void);
|
||||
|
||||
@@ -146,7 +146,7 @@ void LedgerAcquire::trigger(Peer::ref peer, bool timer)
|
||||
if (mAborted || mComplete || mFailed)
|
||||
return;
|
||||
#ifdef LA_DEBUG
|
||||
if(peer) Log(lsTRACE) << "Trigger acquiring ledger " << mHash << " from " << peer->getIP();
|
||||
if (peer) Log(lsTRACE) << "Trigger acquiring ledger " << mHash << " from " << peer->getIP();
|
||||
else Log(lsTRACE) << "Trigger acquiring ledger " << mHash;
|
||||
if (mComplete || mFailed)
|
||||
Log(lsTRACE) << "complete=" << mComplete << " failed=" << mFailed;
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
typedef std::pair<const uint160, LedgerProposal::pointer> u160_prop_pair;
|
||||
typedef std::pair<const uint256, LCTransaction::pointer> u256_lct_pair;
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, TX_ACQUIRE_TIMEOUT), mHaveRoot(false)
|
||||
{
|
||||
mMap = boost::make_shared<SHAMap>(hash);
|
||||
@@ -32,7 +34,7 @@ void TransactionAcquire::done()
|
||||
{
|
||||
if (mFailed)
|
||||
{
|
||||
Log(lsWARNING) << "Failed to acquire TXs " << mHash;
|
||||
cLog(lsWARNING) << "Failed to acquire TXs " << mHash;
|
||||
theApp->getOPs().mapComplete(mHash, SHAMap::pointer());
|
||||
}
|
||||
else
|
||||
@@ -51,12 +53,12 @@ void TransactionAcquire::trigger(Peer::ref peer, bool timer)
|
||||
{
|
||||
if (mComplete || mFailed)
|
||||
{
|
||||
Log(lsINFO) << "complete or failed";
|
||||
cLog(lsINFO) << "complete or failed";
|
||||
return;
|
||||
}
|
||||
if (!mHaveRoot)
|
||||
{
|
||||
Log(lsINFO) << "have no root";
|
||||
cLog(lsINFO) << "have no root";
|
||||
newcoin::TMGetLedger tmGL;
|
||||
tmGL.set_ledgerhash(mHash.begin(), mHash.size());
|
||||
tmGL.set_itype(newcoin::liTS_CANDIDATE);
|
||||
@@ -110,7 +112,7 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
|
||||
{
|
||||
if (mHaveRoot)
|
||||
{
|
||||
Log(lsWARNING) << "Got root TXS node, already have it";
|
||||
cLog(lsWARNING) << "Got root TXS node, already have it";
|
||||
return false;
|
||||
}
|
||||
if (!mMap->addRootNode(getHash(), *nodeDatait, snfWIRE))
|
||||
@@ -129,7 +131,7 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsERROR) << "Peer sends us junky transaction node data";
|
||||
cLog(lsERROR) << "Peer sends us junky transaction node data";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -143,25 +145,25 @@ void LCTransaction::setVote(const uint160& peer, bool votesYes)
|
||||
{ // new vote
|
||||
if (votesYes)
|
||||
{
|
||||
Log(lsTRACE) << "Peer " << peer << " votes YES on " << mTransactionID;
|
||||
cLog(lsTRACE) << "Peer " << peer << " votes YES on " << mTransactionID;
|
||||
++mYays;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "Peer " << peer << " votes NO on " << mTransactionID;
|
||||
cLog(lsTRACE) << "Peer " << peer << " votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
}
|
||||
}
|
||||
else if (votesYes && !res.first->second)
|
||||
{ // changes vote to yes
|
||||
Log(lsTRACE) << "Peer " << peer << " now votes YES on " << mTransactionID;
|
||||
cLog(lsTRACE) << "Peer " << peer << " now votes YES on " << mTransactionID;
|
||||
--mNays;
|
||||
++mYays;
|
||||
res.first->second = true;
|
||||
}
|
||||
else if (!votesYes && res.first->second)
|
||||
{ // changes vote to no
|
||||
Log(lsTRACE) << "Peer " << peer << " now votes NO on " << mTransactionID;
|
||||
cLog(lsTRACE) << "Peer " << peer << " now votes NO on " << mTransactionID;
|
||||
++mNays;
|
||||
--mYays;
|
||||
res.first->second = false;
|
||||
@@ -209,13 +211,13 @@ bool LCTransaction::updateVote(int percentTime, bool proposing)
|
||||
if (newPosition == mOurVote)
|
||||
{
|
||||
#ifdef LC_DEBUG
|
||||
Log(lsTRACE) << "No change (" << (mOurVote ? "YES" : "NO") << ") : weight "
|
||||
cLog(lsTRACE) << "No change (" << (mOurVote ? "YES" : "NO") << ") : weight "
|
||||
<< weight << ", percent " << percentTime;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
mOurVote = newPosition;
|
||||
Log(lsTRACE) << "We now vote " << (mOurVote ? "YES" : "NO") << " on " << mTransactionID;
|
||||
cLog(lsTRACE) << "We now vote " << (mOurVote ? "YES" : "NO") << " on " << mTransactionID;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -224,8 +226,8 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previou
|
||||
mValSeed(theConfig.VALIDATION_SEED), mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false),
|
||||
mConsensusStartTime(boost::posix_time::microsec_clock::universal_time())
|
||||
{
|
||||
Log(lsDEBUG) << "Creating consensus object";
|
||||
Log(lsTRACE) << "LCL:" << previousLedger->getHash() <<", ct=" << closeTime;
|
||||
cLog(lsDEBUG) << "Creating consensus object";
|
||||
cLog(lsTRACE) << "LCL:" << previousLedger->getHash() <<", ct=" << closeTime;
|
||||
mPreviousProposers = theApp->getOPs().getPreviousProposers();
|
||||
mPreviousMSeconds = theApp->getOPs().getPreviousConvergeTime();
|
||||
assert(mPreviousMSeconds);
|
||||
@@ -235,21 +237,21 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previou
|
||||
|
||||
if (mValSeed.isValid())
|
||||
{
|
||||
Log(lsINFO) << "Entering consensus process, validating";
|
||||
cLog(lsINFO) << "Entering consensus process, validating";
|
||||
mValidating = true;
|
||||
mProposing = theApp->getOPs().getOperatingMode() == NetworkOPs::omFULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "Entering consensus process, watching";
|
||||
cLog(lsINFO) << "Entering consensus process, watching";
|
||||
mProposing = mValidating = false;
|
||||
}
|
||||
|
||||
handleLCL(prevLCLHash);
|
||||
if (!mHaveCorrectLCL)
|
||||
{
|
||||
Log(lsINFO) << "Entering consensus with: " << previousLedger->getHash();
|
||||
Log(lsINFO) << "Correct LCL is: " << prevLCLHash;
|
||||
cLog(lsINFO) << "Entering consensus with: " << previousLedger->getHash();
|
||||
cLog(lsINFO) << "Correct LCL is: " << prevLCLHash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,13 +284,13 @@ void LedgerConsensus::checkLCL()
|
||||
default: status = "unknown";
|
||||
}
|
||||
|
||||
Log(lsWARNING) << "View of consensus changed during consensus (" << netLgrCount << ") status="
|
||||
cLog(lsWARNING) << "View of consensus changed during consensus (" << netLgrCount << ") status="
|
||||
<< status << ", " << (mHaveCorrectLCL ? "CorrectLCL" : "IncorrectLCL");
|
||||
Log(lsWARNING) << mPrevLedgerHash << " to " << netLgr;
|
||||
cLog(lsWARNING) << mPrevLedgerHash << " to " << netLgr;
|
||||
|
||||
#ifdef DEBUG
|
||||
BOOST_FOREACH(u256_cvc_pair& it, vals)
|
||||
Log(lsDEBUG) << "V: " << it.first << ", " << it.second.first;
|
||||
cLog(lsDEBUG) << "V: " << it.first << ", " << it.second.first;
|
||||
#endif
|
||||
|
||||
if (mHaveCorrectLCL)
|
||||
@@ -310,7 +312,7 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
|
||||
return;
|
||||
else
|
||||
{
|
||||
Log(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash;
|
||||
cLog(lsWARNING) << "Need consensus ledger " << mPrevLedgerHash;
|
||||
|
||||
mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash);
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
@@ -333,7 +335,7 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
|
||||
|
||||
if (mHaveCorrectLCL && mProposing && mOurPosition)
|
||||
{
|
||||
Log(lsINFO) << "Bowing out of consensus";
|
||||
cLog(lsINFO) << "Bowing out of consensus";
|
||||
mOurPosition->bowOut();
|
||||
propose();
|
||||
}
|
||||
@@ -348,7 +350,7 @@ void LedgerConsensus::handleLCL(const uint256& lclHash)
|
||||
return;
|
||||
}
|
||||
|
||||
Log(lsINFO) << "Acquired the consensus ledger " << mPrevLedgerHash;
|
||||
cLog(lsINFO) << "Acquired the consensus ledger " << mPrevLedgerHash;
|
||||
mHaveCorrectLCL = true;
|
||||
mAcquiringLedger = LedgerAcquire::pointer();
|
||||
mCloseResolution = ContinuousLedgerTiming::getNextLedgerTimeResolution(
|
||||
@@ -361,7 +363,7 @@ void LedgerConsensus::takeInitialPosition(Ledger& initialLedger)
|
||||
{
|
||||
SHAMap::pointer initialSet = initialLedger.peekTransactionMap()->snapShot(false);
|
||||
uint256 txSet = initialSet->getHash();
|
||||
Log(lsINFO) << "initial position " << txSet;
|
||||
cLog(lsINFO) << "initial position " << txSet;
|
||||
mapComplete(txSet, initialSet, false);
|
||||
|
||||
if (mValidating)
|
||||
@@ -415,14 +417,13 @@ void LedgerConsensus::createDisputes(SHAMap::ref m1, SHAMap::ref m2)
|
||||
|
||||
void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::ref map, bool acquired)
|
||||
{
|
||||
if (acquired)
|
||||
Log(lsINFO) << "We have acquired TXS " << hash;
|
||||
tLog(acquired, lsINFO) << "We have acquired TXS " << hash;
|
||||
|
||||
if (!map)
|
||||
{ // this is an invalid/corrupt map
|
||||
mAcquired[hash] = map;
|
||||
mAcquiring.erase(hash);
|
||||
Log(lsWARNING) << "A trusted node directed us to acquire an invalid TXN map";
|
||||
cLog(lsWARNING) << "A trusted node directed us to acquire an invalid TXN map";
|
||||
return;
|
||||
}
|
||||
assert(hash == map->getHash());
|
||||
@@ -456,8 +457,7 @@ void LedgerConsensus::mapComplete(const uint256& hash, SHAMap::ref map, bool acq
|
||||
}
|
||||
if (!peers.empty())
|
||||
adjustCount(map, peers);
|
||||
else if (acquired)
|
||||
Log(lsWARNING) << "By the time we got the map " << hash << " no peers were proposing it";
|
||||
else tLog(acquired, lsWARNING) << "By the time we got the map " << hash << " no peers were proposing it";
|
||||
|
||||
sendHaveTxSet(hash, true);
|
||||
}
|
||||
@@ -496,7 +496,7 @@ void LedgerConsensus::statusChange(newcoin::NodeEvent event, Ledger& ledger)
|
||||
s.set_ledgerhash(hash.begin(), hash.size());
|
||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(s, newcoin::mtSTATUS_CHANGE);
|
||||
theApp->getConnectionPool().relayMessage(NULL, packet);
|
||||
Log(lsINFO) << "send status change to peer";
|
||||
cLog(lsINFO) << "send status change to peer";
|
||||
}
|
||||
|
||||
int LedgerConsensus::startup()
|
||||
@@ -527,15 +527,20 @@ void LedgerConsensus::statePreClose()
|
||||
}
|
||||
|
||||
if (ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed,
|
||||
mPreviousMSeconds, sinceClose, idleInterval))
|
||||
{ // it is time to close the ledger
|
||||
mPreviousMSeconds, sinceClose, idleInterval))
|
||||
{
|
||||
closeLedger();
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::closeLedger()
|
||||
{
|
||||
mState = lcsESTABLISH;
|
||||
mConsensusStartTime = boost::posix_time::microsec_clock::universal_time();
|
||||
mCloseTime = theApp->getOPs().getCloseTimeNC();
|
||||
theApp->getOPs().setLastCloseTime(mCloseTime);
|
||||
statusChange(newcoin::neCLOSING_LEDGER, *mPreviousLedger);
|
||||
takeInitialPosition(*theApp->getMasterLedger().closeLedger());
|
||||
}
|
||||
}
|
||||
|
||||
void LedgerConsensus::stateEstablish()
|
||||
@@ -545,14 +550,13 @@ void LedgerConsensus::stateEstablish()
|
||||
updateOurPositions();
|
||||
if (!mHaveCloseTimeConsensus)
|
||||
{
|
||||
if (haveConsensus())
|
||||
Log(lsINFO) << "We have TX consensus but not CT consensus";
|
||||
tLog(haveConsensus(), lsINFO) << "We have TX consensus but not CT consensus";
|
||||
}
|
||||
else if (haveConsensus())
|
||||
{
|
||||
Log(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)";
|
||||
cLog(lsINFO) << "Converge cutoff (" << mPeerPositions.size() << " participants)";
|
||||
mState = lcsFINISHED;
|
||||
beginAccept();
|
||||
beginAccept(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,7 +609,7 @@ void LedgerConsensus::updateOurPositions()
|
||||
if (it->second->isStale(peerCutoff))
|
||||
{ // proposal is stale
|
||||
uint160 peerID = it->second->getPeerID();
|
||||
Log(lsWARNING) << "Removing stale proposal from " << peerID;
|
||||
cLog(lsWARNING) << "Removing stale proposal from " << peerID;
|
||||
BOOST_FOREACH(u256_lct_pair& it, mDisputes)
|
||||
it.second->unVote(peerID);
|
||||
mPeerPositions.erase(it++);
|
||||
@@ -670,18 +674,17 @@ void LedgerConsensus::updateOurPositions()
|
||||
|
||||
for (std::map<uint32, int>::iterator it = closeTimes.begin(), end = closeTimes.end(); it != end; ++it)
|
||||
{
|
||||
Log(lsINFO) << "CCTime: " << it->first << " has " << it->second << ", " << thresh << " required";
|
||||
cLog(lsINFO) << "CCTime: " << it->first << " has " << it->second << ", " << thresh << " required";
|
||||
if (it->second > thresh)
|
||||
{
|
||||
Log(lsINFO) << "Close time consensus reached: " << it->first;
|
||||
cLog(lsINFO) << "Close time consensus reached: " << it->first;
|
||||
mHaveCloseTimeConsensus = true;
|
||||
closeTime = it->first;
|
||||
thresh = it->second;
|
||||
}
|
||||
}
|
||||
if (!mHaveCloseTimeConsensus)
|
||||
Log(lsDEBUG) << "No CT consensus: Proposers:" << mPeerPositions.size() << " Proposing:" <<
|
||||
(mProposing ? "yes" : "no") << " Thresh:" << thresh << " Pos:" << closeTime;
|
||||
tLog(!mHaveCloseTimeConsensus, lsDEBUG) << "No CT consensus: Proposers:" << mPeerPositions.size()
|
||||
<< " Proposing:" << (mProposing ? "yes" : "no") << " Thresh:" << thresh << " Pos:" << closeTime;
|
||||
}
|
||||
|
||||
if ((!changes) &&
|
||||
@@ -696,7 +699,7 @@ void LedgerConsensus::updateOurPositions()
|
||||
if (changes)
|
||||
{
|
||||
uint256 newHash = ourPosition->getHash();
|
||||
Log(lsINFO) << "Position change: CTime " << closeTime << ", tx " << newHash;
|
||||
cLog(lsINFO) << "Position change: CTime " << closeTime << ", tx " << newHash;
|
||||
if (mOurPosition->changePosition(newHash, closeTime))
|
||||
{
|
||||
if (mProposing)
|
||||
@@ -724,7 +727,7 @@ bool LedgerConsensus::haveConsensus()
|
||||
int currentValidations = theApp->getValidations().getNodesAfter(mPrevLedgerHash);
|
||||
|
||||
#ifdef LC_DEBUG
|
||||
Log(lsINFO) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
|
||||
cLog(lsINFO) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
|
||||
#endif
|
||||
|
||||
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
|
||||
@@ -742,7 +745,7 @@ SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool do
|
||||
SHAMap::pointer currentMap = theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap();
|
||||
if (currentMap->getHash() == hash)
|
||||
{
|
||||
Log(lsINFO) << "node proposes our open transaction set";
|
||||
cLog(lsINFO) << "node proposes our open transaction set";
|
||||
currentMap = currentMap->snapShot(false);
|
||||
mapComplete(hash, currentMap, false);
|
||||
return currentMap;
|
||||
@@ -803,7 +806,7 @@ void LedgerConsensus::startAcquiring(const TransactionAcquire::pointer& acquire)
|
||||
|
||||
void LedgerConsensus::propose()
|
||||
{
|
||||
Log(lsTRACE) << "We propose: " << mOurPosition->getCurrentHash();
|
||||
cLog(lsTRACE) << "We propose: " << mOurPosition->getCurrentHash();
|
||||
newcoin::TMProposeSet prop;
|
||||
prop.set_currenttxhash(mOurPosition->getCurrentHash().begin(), 256 / 8);
|
||||
prop.set_proposeseq(mOurPosition->getProposeSeq());
|
||||
@@ -819,7 +822,7 @@ void LedgerConsensus::propose()
|
||||
|
||||
void LedgerConsensus::addDisputedTransaction(const uint256& txID, const std::vector<unsigned char>& tx)
|
||||
{
|
||||
Log(lsTRACE) << "Transaction " << txID << " is disputed";
|
||||
cLog(lsTRACE) << "Transaction " << txID << " is disputed";
|
||||
boost::unordered_map<uint256, LCTransaction::pointer>::iterator it = mDisputes.find(txID);
|
||||
if (it != mDisputes.end())
|
||||
return;
|
||||
@@ -861,7 +864,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
|
||||
uint160 peerID = newPosition->getPeerID();
|
||||
if (mDeadNodes.find(peerID) != mDeadNodes.end())
|
||||
{
|
||||
Log(lsINFO) << "Position from dead node";
|
||||
cLog(lsINFO) << "Position from dead node";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -876,7 +879,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
|
||||
|
||||
if (newPosition->getProposeSeq() == 0)
|
||||
{ // new initial close time estimate
|
||||
Log(lsTRACE) << "Peer reports close time as " << newPosition->getCloseTime();
|
||||
cLog(lsTRACE) << "Peer reports close time as " << newPosition->getCloseTime();
|
||||
++mCloseTimes[newPosition->getCloseTime()];
|
||||
}
|
||||
else if (newPosition->getProposeSeq() == LedgerProposal::seqLeave)
|
||||
@@ -889,7 +892,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
|
||||
}
|
||||
|
||||
|
||||
Log(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash();
|
||||
cLog(lsINFO) << "Processing peer proposal " << newPosition->getProposeSeq() << "/" << newPosition->getCurrentHash();
|
||||
currentPosition = newPosition;
|
||||
|
||||
SHAMap::pointer set = getTransactionTree(newPosition->getCurrentHash(), true);
|
||||
@@ -899,7 +902,7 @@ bool LedgerConsensus::peerPosition(const LedgerProposal::pointer& newPosition)
|
||||
it.second->setVote(peerID, set->hasItem(it.first));
|
||||
}
|
||||
else
|
||||
Log(lsTRACE) << "Don't have that tx set";
|
||||
cLog(lsTRACE) << "Don't have that tx set";
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -931,18 +934,21 @@ bool LedgerConsensus::peerGaveNodes(Peer::ref peer, const uint256& setHash,
|
||||
return set->takeNodes(nodeIDs, nodeData, peer);
|
||||
}
|
||||
|
||||
void LedgerConsensus::beginAccept()
|
||||
void LedgerConsensus::beginAccept(bool synchronous)
|
||||
{
|
||||
SHAMap::pointer consensusSet = mAcquired[mOurPosition->getCurrentHash()];
|
||||
if (!consensusSet)
|
||||
{
|
||||
Log(lsFATAL) << "We don't have a consensus set";
|
||||
cLog(lsFATAL) << "We don't have a consensus set";
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
|
||||
theApp->getOPs().newLCL(mPeerPositions.size(), mCurrentMSeconds, mNewLedgerHash);
|
||||
theApp->getIOService().post(boost::bind(&LedgerConsensus::Saccept, shared_from_this(), consensusSet));
|
||||
if (synchronous)
|
||||
accept(consensusSet);
|
||||
else
|
||||
theApp->getIOService().post(boost::bind(&LedgerConsensus::Saccept, shared_from_this(), consensusSet));
|
||||
}
|
||||
|
||||
void LedgerConsensus::Saccept(boost::shared_ptr<LedgerConsensus> This, SHAMap::pointer txSet)
|
||||
@@ -970,7 +976,7 @@ void LedgerConsensus::playbackProposals()
|
||||
proposal->setPrevLedger(mPrevLedgerHash);
|
||||
if (proposal->checkSign())
|
||||
{
|
||||
Log(lsINFO) << "Applying deferred proposal";
|
||||
cLog(lsINFO) << "Applying deferred proposal";
|
||||
peerPosition(proposal);
|
||||
}
|
||||
}
|
||||
@@ -991,18 +997,18 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ
|
||||
TER result = engine.applyTransaction(*txn, parms);
|
||||
if (isTerRetry(result))
|
||||
{
|
||||
Log(lsINFO) << " retry";
|
||||
cLog(lsINFO) << " retry";
|
||||
assert(!ledger->hasTransaction(txn->getTransactionID()));
|
||||
failedTransactions.push_back(txn);
|
||||
}
|
||||
else if (isTepSuccess(result)) // FIXME: Need to do partial success
|
||||
{
|
||||
Log(lsTRACE) << " success";
|
||||
cLog(lsTRACE) << " success";
|
||||
assert(ledger->hasTransaction(txn->getTransactionID()));
|
||||
}
|
||||
else if (isTemMalformed(result) || isTefFailure(result))
|
||||
{
|
||||
Log(lsINFO) << " hard fail";
|
||||
cLog(lsINFO) << " hard fail";
|
||||
}
|
||||
else
|
||||
assert(false);
|
||||
@@ -1010,7 +1016,7 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
cLog(lsWARNING) << " Throws";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1025,7 +1031,7 @@ void LedgerConsensus::applyTransactions(SHAMap::ref set, Ledger::ref applyLedger
|
||||
{
|
||||
if (!checkLedger->hasTransaction(item->getTag()))
|
||||
{
|
||||
Log(lsINFO) << "Processing candidate transaction: " << item->getTag();
|
||||
cLog(lsINFO) << "Processing candidate transaction: " << item->getTag();
|
||||
#ifndef TRUST_NETWORK
|
||||
try
|
||||
{
|
||||
@@ -1037,7 +1043,7 @@ void LedgerConsensus::applyTransactions(SHAMap::ref set, Ledger::ref applyLedger
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
cLog(lsWARNING) << " Throws";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1065,7 +1071,7 @@ void LedgerConsensus::applyTransactions(SHAMap::ref set, Ledger::ref applyLedger
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << " Throws";
|
||||
cLog(lsWARNING) << " Throws";
|
||||
it = failedTransactions.erase(it);
|
||||
}
|
||||
}
|
||||
@@ -1083,11 +1089,11 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
|
||||
uint32 closeTime = roundCloseTime(mOurPosition->getCloseTime());
|
||||
|
||||
Log(lsINFO) << "Computing new LCL based on network consensus";
|
||||
cLog(lsINFO) << "Computing new LCL based on network consensus";
|
||||
if (mHaveCorrectLCL)
|
||||
{
|
||||
Log(lsINFO) << "CNF tx " << mOurPosition->getCurrentHash() << ", close " << closeTime;
|
||||
Log(lsINFO) << "CNF mode " << theApp->getOPs().getOperatingMode() << ", oldLCL " << mPrevLedgerHash;
|
||||
cLog(lsINFO) << "CNF tx " << mOurPosition->getCurrentHash() << ", close " << closeTime;
|
||||
cLog(lsINFO) << "CNF mode " << theApp->getOPs().getOperatingMode() << ", oldLCL " << mPrevLedgerHash;
|
||||
}
|
||||
|
||||
Ledger::pointer newLCL = boost::make_shared<Ledger>(false, boost::ref(*mPreviousLedger));
|
||||
@@ -1102,7 +1108,7 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
{ // we agreed to disagree
|
||||
closeTimeCorrect = false;
|
||||
closeTime = mPreviousLedger->getCloseTimeNC() + 1;
|
||||
Log(lsINFO) << "CNF badclose " << closeTime;
|
||||
cLog(lsINFO) << "CNF badclose " << closeTime;
|
||||
}
|
||||
|
||||
newLCL->setAccepted(closeTime, mCloseResolution, closeTimeCorrect);
|
||||
@@ -1120,10 +1126,10 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
val.set_validation(&validation[0], validation.size());
|
||||
int j = theApp->getConnectionPool().relayMessage(NULL,
|
||||
boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
|
||||
Log(lsINFO) << "CNF Val " << newLCLHash << " to " << j << " peers";
|
||||
cLog(lsINFO) << "CNF Val " << newLCLHash << " to " << j << " peers";
|
||||
}
|
||||
else
|
||||
Log(lsINFO) << "CNF newLCL " << newLCLHash;
|
||||
cLog(lsINFO) << "CNF newLCL " << newLCLHash;
|
||||
|
||||
Ledger::pointer newOL = boost::make_shared<Ledger>(true, boost::ref(*newLCL));
|
||||
ScopedLock sl = theApp->getMasterLedger().getLock();
|
||||
@@ -1136,19 +1142,19 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
{ // we voted NO
|
||||
try
|
||||
{
|
||||
Log(lsINFO) << "Test applying disputed transaction that did not get in";
|
||||
cLog(lsINFO) << "Test applying disputed transaction that did not get in";
|
||||
SerializerIterator sit(it.second->peekTransaction());
|
||||
SerializedTransaction::pointer txn = boost::make_shared<SerializedTransaction>(boost::ref(sit));
|
||||
applyTransaction(engine, txn, newOL, failedTransactions, true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsINFO) << "Failed to apply transaction we voted NO on";
|
||||
cLog(lsINFO) << "Failed to apply transaction we voted NO on";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << "Applying transactions from current ledger";
|
||||
cLog(lsINFO) << "Applying transactions from current ledger";
|
||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, newLCL,
|
||||
failedTransactions, true);
|
||||
theApp->getMasterLedger().pushLedger(newLCL, newOL);
|
||||
@@ -1158,12 +1164,12 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
|
||||
if (mValidating)
|
||||
{ // see how close our close time is to other node's close time reports
|
||||
Log(lsINFO) << "We closed at " << boost::lexical_cast<std::string>(mCloseTime);
|
||||
cLog(lsINFO) << "We closed at " << boost::lexical_cast<std::string>(mCloseTime);
|
||||
uint64 closeTotal = mCloseTime;
|
||||
int closeCount = 1;
|
||||
for (std::map<uint32, int>::iterator it = mCloseTimes.begin(), end = mCloseTimes.end(); it != end; ++it)
|
||||
{ // FIXME: Use median, not average
|
||||
Log(lsINFO) << boost::lexical_cast<std::string>(it->second) << " time votes for "
|
||||
cLog(lsINFO) << boost::lexical_cast<std::string>(it->second) << " time votes for "
|
||||
<< boost::lexical_cast<std::string>(it->first);
|
||||
closeCount += it->second;
|
||||
closeTotal += static_cast<uint64>(it->first) * static_cast<uint64>(it->second);
|
||||
@@ -1171,19 +1177,17 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
closeTotal += (closeCount / 2);
|
||||
closeTotal /= closeCount;
|
||||
int offset = static_cast<int>(closeTotal) - static_cast<int>(mCloseTime);
|
||||
Log(lsINFO) << "Our close offset is estimated at " << offset << " (" << closeCount << ")";
|
||||
cLog(lsINFO) << "Our close offset is estimated at " << offset << " (" << closeCount << ")";
|
||||
theApp->getOPs().closeTimeOffset(offset);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (sLog(lsTRACE))
|
||||
{
|
||||
Json::StyledStreamWriter ssw;
|
||||
Log(lsTRACE) << "newLCL";
|
||||
Json::Value p;
|
||||
newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
|
||||
ssw.write(Log(lsTRACE).ref(), p);
|
||||
Log(lsTRACE) << p;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LedgerConsensus::endConsensus()
|
||||
@@ -1191,6 +1195,16 @@ void LedgerConsensus::endConsensus()
|
||||
theApp->getOPs().endConsensus(mHaveCorrectLCL);
|
||||
}
|
||||
|
||||
void LedgerConsensus::simulate()
|
||||
{
|
||||
cLog(lsINFO) << "Simulating consensus";
|
||||
closeLedger();
|
||||
mCurrentMSeconds = 100;
|
||||
beginAccept(true);
|
||||
endConsensus();
|
||||
cLog(lsINFO) << "Simulation complete";
|
||||
}
|
||||
|
||||
Json::Value LedgerConsensus::getJson()
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
|
||||
@@ -148,8 +148,9 @@ protected:
|
||||
void updateOurPositions();
|
||||
void playbackProposals();
|
||||
int getThreshold();
|
||||
void closeLedger();
|
||||
|
||||
void beginAccept();
|
||||
void beginAccept(bool synchronous);
|
||||
void endConsensus();
|
||||
|
||||
public:
|
||||
@@ -189,6 +190,8 @@ public:
|
||||
void swapDefer(boost::unordered_map< uint160, std::list<LedgerProposal::pointer> > &n)
|
||||
{ mDeferredProposals.swap(n); }
|
||||
|
||||
// test/debug
|
||||
void simulate();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
// #define META_DEBUG
|
||||
|
||||
// Small for testing, should likely be 32 or 64.
|
||||
@@ -297,7 +299,7 @@ bool LedgerEntrySet::threadTx(const NewcoinAddress& threadTo, Ledger::ref ledger
|
||||
boost::unordered_map<uint256, SLE::pointer>& newMods)
|
||||
{
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Thread to " << threadTo.getAccountID();
|
||||
cLog(lsTRACE) << "Thread to " << threadTo.getAccountID();
|
||||
#endif
|
||||
SLE::pointer sle = getForMod(Ledger::getAccountRootIndex(threadTo.getAccountID()), ledger, newMods);
|
||||
if (!sle)
|
||||
@@ -326,14 +328,14 @@ bool LedgerEntrySet::threadOwners(SLE::ref node, Ledger::ref ledger, boost::unor
|
||||
if (node->hasOneOwner()) // thread to owner's account
|
||||
{
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Thread to single owner";
|
||||
cLog(lsTRACE) << "Thread to single owner";
|
||||
#endif
|
||||
return threadTx(node->getOwner(), ledger, newMods);
|
||||
}
|
||||
else if (node->hasTwoOwners()) // thread to owner's accounts]
|
||||
{
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Thread to two owners";
|
||||
cLog(lsTRACE) << "Thread to two owners";
|
||||
#endif
|
||||
return
|
||||
threadTx(node->getFirstOwner(), ledger, newMods) &&
|
||||
@@ -358,21 +360,21 @@ void LedgerEntrySet::calcRawMeta(Serializer& s)
|
||||
{
|
||||
case taaMODIFY:
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Modified Node " << it->first;
|
||||
cLog(lsTRACE) << "Modified Node " << it->first;
|
||||
#endif
|
||||
nType = TMNModifiedNode;
|
||||
break;
|
||||
|
||||
case taaDELETE:
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Deleted Node " << it->first;
|
||||
cLog(lsTRACE) << "Deleted Node " << it->first;
|
||||
#endif
|
||||
nType = TMNDeletedNode;
|
||||
break;
|
||||
|
||||
case taaCREATE:
|
||||
#ifdef META_DEBUG
|
||||
Log(lsTRACE) << "Created Node " << it->first;
|
||||
cLog(lsTRACE) << "Created Node " << it->first;
|
||||
#endif
|
||||
nType = TMNCreatedNode;
|
||||
break;
|
||||
@@ -466,7 +468,7 @@ void LedgerEntrySet::calcRawMeta(Serializer& s)
|
||||
entryModify(it->second);
|
||||
|
||||
#ifdef META_DEBUG
|
||||
Log(lsINFO) << "Metadata:" << mSet.getJson(0);
|
||||
cLog(lsINFO) << "Metadata:" << mSet.getJson(0);
|
||||
#endif
|
||||
|
||||
mSet.addRaw(s);
|
||||
@@ -557,10 +559,10 @@ TER LedgerEntrySet::dirAdd(
|
||||
svIndexes.peekValue().push_back(uLedgerIndex); // Append entry.
|
||||
sleNode->setFieldV256(sfIndexes, svIndexes); // Save entry.
|
||||
|
||||
Log(lsINFO) << "dirAdd: creating: root: " << uRootIndex.ToString();
|
||||
Log(lsINFO) << "dirAdd: appending: Entry: " << uLedgerIndex.ToString();
|
||||
Log(lsINFO) << "dirAdd: appending: Node: " << strHex(uNodeDir);
|
||||
// Log(lsINFO) << "dirAdd: appending: PREV: " << svIndexes.peekValue()[0].ToString();
|
||||
cLog(lsINFO) << "dirAdd: creating: root: " << uRootIndex.ToString();
|
||||
cLog(lsINFO) << "dirAdd: appending: Entry: " << uLedgerIndex.ToString();
|
||||
cLog(lsINFO) << "dirAdd: appending: Node: " << strHex(uNodeDir);
|
||||
// cLog(lsINFO) << "dirAdd: appending: PREV: " << svIndexes.peekValue()[0].ToString();
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
@@ -580,7 +582,7 @@ TER LedgerEntrySet::dirDelete(
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: no such node";
|
||||
cLog(lsWARNING) << "dirDelete: no such node";
|
||||
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
@@ -596,7 +598,7 @@ TER LedgerEntrySet::dirDelete(
|
||||
{
|
||||
assert(false);
|
||||
|
||||
Log(lsWARNING) << "dirDelete: no such entry";
|
||||
cLog(lsWARNING) << "dirDelete: no such entry";
|
||||
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
@@ -688,14 +690,14 @@ TER LedgerEntrySet::dirDelete(
|
||||
|
||||
if (!slePrevious)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: previous node is missing";
|
||||
cLog(lsWARNING) << "dirDelete: previous node is missing";
|
||||
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
|
||||
if (!sleNext)
|
||||
{
|
||||
Log(lsWARNING) << "dirDelete: next node is missing";
|
||||
cLog(lsWARNING) << "dirDelete: next node is missing";
|
||||
|
||||
return tefBAD_LEDGER;
|
||||
}
|
||||
@@ -789,7 +791,7 @@ bool LedgerEntrySet::dirNext(
|
||||
}
|
||||
|
||||
uEntryIndex = vuiIndexes[uDirEntry++];
|
||||
Log(lsINFO) << boost::str(boost::format("dirNext: uDirEntry=%d uEntryIndex=%s") % uDirEntry % uEntryIndex);
|
||||
cLog(lsINFO) << boost::str(boost::format("dirNext: uDirEntry=%d uEntryIndex=%s") % uDirEntry % uEntryIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -836,7 +838,7 @@ STAmount LedgerEntrySet::rippleOwed(const uint160& uToAccountID, const uint160&
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "rippleOwed: No credit line between "
|
||||
cLog(lsINFO) << "rippleOwed: No credit line between "
|
||||
<< NewcoinAddress::createHumanAccountID(uFromAccountID)
|
||||
<< " and "
|
||||
<< NewcoinAddress::createHumanAccountID(uToAccountID)
|
||||
@@ -876,7 +878,7 @@ uint32 LedgerEntrySet::rippleTransferRate(const uint160& uIssuerID)
|
||||
? sleAccount->getFieldU32(sfTransferRate)
|
||||
: QUALITY_ONE;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("rippleTransferRate: uIssuerID=%s account_exists=%d transfer_rate=%f")
|
||||
cLog(lsINFO) << boost::str(boost::format("rippleTransferRate: uIssuerID=%s account_exists=%d transfer_rate=%f")
|
||||
% NewcoinAddress::createHumanAccountID(uIssuerID)
|
||||
% !!sleAccount
|
||||
% (uQuality/1000000000.0));
|
||||
@@ -888,8 +890,6 @@ uint32 LedgerEntrySet::rippleTransferRate(const uint160& uIssuerID)
|
||||
|
||||
uint32 LedgerEntrySet::rippleTransferRate(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID)
|
||||
{
|
||||
uint32 uQuality;
|
||||
|
||||
return uSenderID == uIssuerID || uReceiverID == uIssuerID
|
||||
? QUALITY_ONE
|
||||
: rippleTransferRate(uIssuerID);
|
||||
@@ -922,7 +922,7 @@ uint32 LedgerEntrySet::rippleQualityIn(const uint160& uToAccountID, const uint16
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("rippleQuality: %s uToAccountID=%s uFromAccountID=%s uCurrencyID=%s bLine=%d uQuality=%f")
|
||||
cLog(lsINFO) << boost::str(boost::format("rippleQuality: %s uToAccountID=%s uFromAccountID=%s uCurrencyID=%s bLine=%d uQuality=%f")
|
||||
% (sfLow == sfLowQualityIn ? "in" : "out")
|
||||
% NewcoinAddress::createHumanAccountID(uToAccountID)
|
||||
% NewcoinAddress::createHumanAccountID(uFromAccountID)
|
||||
@@ -969,7 +969,7 @@ STAmount LedgerEntrySet::accountHolds(const uint160& uAccountID, const uint160&
|
||||
saAmount = rippleHolds(uAccountID, uCurrencyID, uIssuerID);
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("accountHolds: uAccountID=%s saAmount=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("accountHolds: uAccountID=%s saAmount=%s")
|
||||
% NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
% saAmount.getFullText());
|
||||
|
||||
@@ -989,7 +989,7 @@ STAmount LedgerEntrySet::accountFunds(const uint160& uAccountID, const STAmount&
|
||||
{
|
||||
saFunds = saDefault;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("accountFunds: uAccountID=%s saDefault=%s SELF-FUNDED")
|
||||
cLog(lsINFO) << boost::str(boost::format("accountFunds: uAccountID=%s saDefault=%s SELF-FUNDED")
|
||||
% NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
% saDefault.getFullText());
|
||||
}
|
||||
@@ -997,7 +997,7 @@ STAmount LedgerEntrySet::accountFunds(const uint160& uAccountID, const STAmount&
|
||||
{
|
||||
saFunds = accountHolds(uAccountID, saDefault.getCurrency(), saDefault.getIssuer());
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("accountFunds: uAccountID=%s saDefault=%s saFunds=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("accountFunds: uAccountID=%s saDefault=%s saFunds=%s")
|
||||
% NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
% saDefault.getFullText()
|
||||
% saFunds.getFullText());
|
||||
@@ -1040,7 +1040,7 @@ void LedgerEntrySet::rippleCredit(const uint160& uSenderID, const uint160& uRece
|
||||
|
||||
if (!sleRippleState)
|
||||
{
|
||||
Log(lsINFO) << "rippleCredit: Creating ripple line: " << uIndex.ToString();
|
||||
cLog(lsINFO) << "rippleCredit: Creating ripple line: " << uIndex.ToString();
|
||||
|
||||
STAmount saBalance = saAmount;
|
||||
|
||||
@@ -1124,7 +1124,7 @@ void LedgerEntrySet::accountSend(const uint160& uSenderID, const uint160& uRecei
|
||||
? entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uReceiverID))
|
||||
: SLE::pointer();
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("accountSend> %s (%s) -> %s (%s) : %s")
|
||||
cLog(lsINFO) << boost::str(boost::format("accountSend> %s (%s) -> %s (%s) : %s")
|
||||
% NewcoinAddress::createHumanAccountID(uSenderID)
|
||||
% (sleSender ? (sleSender->getFieldAmount(sfBalance)).getFullText() : "-")
|
||||
% NewcoinAddress::createHumanAccountID(uReceiverID)
|
||||
@@ -1143,7 +1143,7 @@ void LedgerEntrySet::accountSend(const uint160& uSenderID, const uint160& uRecei
|
||||
entryModify(sleReceiver);
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("accountSend< %s (%s) -> %s (%s) : %s")
|
||||
cLog(lsINFO) << boost::str(boost::format("accountSend< %s (%s) -> %s (%s) : %s")
|
||||
% NewcoinAddress::createHumanAccountID(uSenderID)
|
||||
% (sleSender ? (sleSender->getFieldAmount(sfBalance)).getFullText() : "-")
|
||||
% NewcoinAddress::createHumanAccountID(uReceiverID)
|
||||
|
||||
@@ -43,8 +43,6 @@ public:
|
||||
// The finalized ledger is the last closed/accepted ledger
|
||||
Ledger::pointer getClosedLedger() { return mFinalizedLedger; }
|
||||
|
||||
void runStandAlone() { mFinalizedLedger = mCurrentLedger; }
|
||||
|
||||
TER doTransaction(const SerializedTransaction& txn, TransactionEngineParams params);
|
||||
|
||||
void pushLedger(Ledger::ref newLedger);
|
||||
|
||||
19
src/Log.cpp
19
src/Log.cpp
@@ -13,6 +13,8 @@ std::ofstream* Log::outStream = NULL;
|
||||
boost::filesystem::path *Log::pathToLog = NULL;
|
||||
uint32 Log::logRotateCounter = 0;
|
||||
|
||||
LogPartition* LogPartition::headLog = NULL;
|
||||
|
||||
Log::~Log()
|
||||
{
|
||||
std::string logMsg = boost::posix_time::to_simple_string(boost::posix_time::second_clock::universal_time());
|
||||
@@ -79,6 +81,7 @@ void Log::setMinSeverity(LogSeverity s)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock sl(sLock);
|
||||
sMinSeverity = s;
|
||||
LogPartition::setSeverity(s);
|
||||
}
|
||||
|
||||
void Log::setLogFile(boost::filesystem::path path)
|
||||
@@ -99,3 +102,19 @@ void Log::setLogFile(boost::filesystem::path path)
|
||||
|
||||
pathToLog = new boost::filesystem::path(path);
|
||||
}
|
||||
|
||||
void LogPartition::setSeverity(const char *partition, LogSeverity severity)
|
||||
{
|
||||
for (LogPartition *p = headLog; p != NULL; p = p->mNextLog)
|
||||
if (p->mName == partition)
|
||||
{
|
||||
p->mMinSeverity = severity;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void LogPartition::setSeverity(LogSeverity severity)
|
||||
{
|
||||
for (LogPartition *p = headLog; p != NULL; p = p->mNextLog)
|
||||
p->mMinSeverity = severity;
|
||||
}
|
||||
|
||||
54
src/Log.h
54
src/Log.h
@@ -2,6 +2,8 @@
|
||||
#define __LOG__
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -10,16 +12,54 @@
|
||||
#include "../json/json.h"
|
||||
|
||||
#include "types.h"
|
||||
#include <limits>
|
||||
|
||||
// Put at the beginning of a C++ file that needs its own log partition
|
||||
#define SETUP_LOG() static LogPartition logPartition(__FILE__)
|
||||
|
||||
// Standard conditional log
|
||||
#define cLog(x) if (!logPartition.doLog(x)) do {} while (0); else Log(x)
|
||||
|
||||
// Log only if an additional condition 'c' is true. Condition is not computed if not needed
|
||||
#define tLog(c,x) if (!logPartition.doLog(x) || !(c)) do {} while(0); else Log(x)
|
||||
|
||||
// Check if should log
|
||||
#define sLog(x) (logPartition.doLog(x))
|
||||
|
||||
|
||||
enum LogSeverity
|
||||
{
|
||||
lsTRACE = 0,
|
||||
lsDEBUG = 1,
|
||||
lsINFO = 2,
|
||||
lsWARNING = 3,
|
||||
lsERROR = 4,
|
||||
lsFATAL = 5
|
||||
lsTRACE = 0, // Very low-level progress information, details inside an operation
|
||||
lsDEBUG = 1, // Function-level progress information, operations
|
||||
lsINFO = 2, // Server-level progress information, major operations
|
||||
lsWARNING = 3, // Conditions that warrant human attention, may indicate a problem
|
||||
lsERROR = 4, // A condition that indicates a problem
|
||||
lsFATAL = 5 // A severe condition that indicates a server problem
|
||||
};
|
||||
|
||||
class LogPartition
|
||||
{
|
||||
protected:
|
||||
static LogPartition* headLog;
|
||||
|
||||
LogPartition* mNextLog;
|
||||
LogSeverity mMinSeverity;
|
||||
std::string mName;
|
||||
|
||||
public:
|
||||
LogPartition(const char *name) : mNextLog(headLog), mMinSeverity(lsWARNING)
|
||||
{
|
||||
const char *ptr = strrchr(name, '/');
|
||||
mName = (ptr == NULL) ? name : ptr;
|
||||
headLog = this;
|
||||
}
|
||||
|
||||
bool doLog(enum LogSeverity s)
|
||||
{
|
||||
return s >= mMinSeverity;
|
||||
}
|
||||
|
||||
static void setSeverity(const char *partition, LogSeverity severity);
|
||||
static void setSeverity(LogSeverity severity);
|
||||
};
|
||||
|
||||
class Log
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
// code assumes this node is synched (and will continue to do so until
|
||||
// there's a functional network.
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
NetworkOPs::NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster) :
|
||||
mMode(omDISCONNECTED),mNetTimer(io_service), mLedgerMaster(pLedgerMaster), mCloseTimeOffset(0),
|
||||
mLastCloseProposers(0), mLastCloseConvergeTime(1000 * LEDGER_IDLE_INTERVAL), mLastValidationTime(0)
|
||||
@@ -63,8 +65,7 @@ void NetworkOPs::closeTimeOffset(int offset)
|
||||
mCloseTimeOffset += (offset - 3) / 4;
|
||||
else
|
||||
mCloseTimeOffset = (mCloseTimeOffset * 3) / 4;
|
||||
if (mCloseTimeOffset)
|
||||
Log(lsINFO) << "Close time offset now " << mCloseTimeOffset;
|
||||
tLog(mCloseTimeOffset != 0, lsINFO) << "Close time offset now " << mCloseTimeOffset;
|
||||
}
|
||||
|
||||
uint32 NetworkOPs::getLedgerID(const uint256& hash)
|
||||
@@ -90,9 +91,9 @@ Transaction::pointer NetworkOPs::submitTransaction(const Transaction::pointer& t
|
||||
|
||||
if(!tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction()))
|
||||
{
|
||||
Log(lsFATAL) << "Transaction reconstruction failure";
|
||||
Log(lsFATAL) << tpTransNew->getSTransaction()->getJson(0);
|
||||
Log(lsFATAL) << tpTrans->getSTransaction()->getJson(0);
|
||||
cLog(lsFATAL) << "Transaction reconstruction failure";
|
||||
cLog(lsFATAL) << tpTransNew->getSTransaction()->getJson(0);
|
||||
cLog(lsFATAL) << tpTrans->getSTransaction()->getJson(0);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
|
||||
if (!trans->checkSign())
|
||||
{
|
||||
Log(lsINFO) << "Transaction has bad signature";
|
||||
cLog(lsINFO) << "Transaction has bad signature";
|
||||
trans->setStatus(INVALID);
|
||||
return trans;
|
||||
}
|
||||
@@ -119,8 +120,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
if (r != tesSUCCESS)
|
||||
{
|
||||
std::string token, human;
|
||||
if (transResultInfo(r, token, human))
|
||||
Log(lsINFO) << "TransactionResult: " << token << ": " << human;
|
||||
tLog(transResultInfo(r, token, human), lsINFO) << "TransactionResult: " << token << ": " << human;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -129,7 +129,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
|
||||
if (r == terPRE_SEQ)
|
||||
{ // transaction should be held
|
||||
Log(lsDEBUG) << "Transaction should be held";
|
||||
cLog(lsDEBUG) << "Transaction should be held";
|
||||
trans->setStatus(HELD);
|
||||
theApp->getMasterTransaction().canonicalize(trans, true);
|
||||
mLedgerMaster->addHeldTransaction(trans);
|
||||
@@ -137,14 +137,14 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
}
|
||||
if ((r == tefPAST_SEQ))
|
||||
{ // duplicate or conflict
|
||||
Log(lsINFO) << "Transaction is obsolete";
|
||||
cLog(lsINFO) << "Transaction is obsolete";
|
||||
trans->setStatus(OBSOLETE);
|
||||
return trans;
|
||||
}
|
||||
|
||||
if (r == tesSUCCESS)
|
||||
{
|
||||
Log(lsINFO) << "Transaction is now included";
|
||||
cLog(lsINFO) << "Transaction is now included";
|
||||
trans->setStatus(INCLUDED);
|
||||
theApp->getMasterTransaction().canonicalize(trans, true);
|
||||
|
||||
@@ -162,12 +162,12 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
||||
|
||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(tx, newcoin::mtTRANSACTION);
|
||||
int sentTo = theApp->getConnectionPool().relayMessage(source, packet);
|
||||
Log(lsINFO) << "Transaction relayed to " << sentTo << " node(s)";
|
||||
cLog(lsINFO) << "Transaction relayed to " << sentTo << " node(s)";
|
||||
|
||||
return trans;
|
||||
}
|
||||
|
||||
Log(lsDEBUG) << "Status other than success " << r;
|
||||
cLog(lsDEBUG) << "Status other than success " << r;
|
||||
if ((mMode != omFULL) && (mMode != omTRACKING) && (theApp->isNew(trans->getID())))
|
||||
{
|
||||
newcoin::TMTransaction tx;
|
||||
@@ -255,21 +255,21 @@ STVector256 NetworkOPs::getDirNodeInfo(
|
||||
|
||||
if (sleNode)
|
||||
{
|
||||
Log(lsDEBUG) << "getDirNodeInfo: node index: " << uNodeIndex.ToString();
|
||||
cLog(lsDEBUG) << "getDirNodeInfo: node index: " << uNodeIndex.ToString();
|
||||
|
||||
Log(lsTRACE) << "getDirNodeInfo: first: " << strHex(sleNode->getFieldU64(sfIndexPrevious));
|
||||
Log(lsTRACE) << "getDirNodeInfo: last: " << strHex(sleNode->getFieldU64(sfIndexNext));
|
||||
cLog(lsTRACE) << "getDirNodeInfo: first: " << strHex(sleNode->getFieldU64(sfIndexPrevious));
|
||||
cLog(lsTRACE) << "getDirNodeInfo: last: " << strHex(sleNode->getFieldU64(sfIndexNext));
|
||||
|
||||
uNodePrevious = sleNode->getFieldU64(sfIndexPrevious);
|
||||
uNodeNext = sleNode->getFieldU64(sfIndexNext);
|
||||
svIndexes = sleNode->getFieldV256(sfIndexes);
|
||||
|
||||
Log(lsTRACE) << "getDirNodeInfo: first: " << strHex(uNodePrevious);
|
||||
Log(lsTRACE) << "getDirNodeInfo: last: " << strHex(uNodeNext);
|
||||
cLog(lsTRACE) << "getDirNodeInfo: first: " << strHex(uNodePrevious);
|
||||
cLog(lsTRACE) << "getDirNodeInfo: last: " << strHex(uNodeNext);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "getDirNodeInfo: node index: NOT FOUND: " << uNodeIndex.ToString();
|
||||
cLog(lsINFO) << "getDirNodeInfo: node index: NOT FOUND: " << uNodeIndex.ToString();
|
||||
|
||||
uNodePrevious = 0;
|
||||
uNodeNext = 0;
|
||||
@@ -403,7 +403,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
if (mMode != omDISCONNECTED)
|
||||
{
|
||||
setMode(omDISCONNECTED);
|
||||
Log(lsWARNING) << "Node count (" << peerList.size() <<
|
||||
cLog(lsWARNING) << "Node count (" << peerList.size() <<
|
||||
") has fallen below quorum (" << theConfig.NETWORK_QUORUM << ").";
|
||||
}
|
||||
return;
|
||||
@@ -411,7 +411,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
if (mMode == omDISCONNECTED)
|
||||
{
|
||||
setMode(omCONNECTED);
|
||||
Log(lsINFO) << "Node count (" << peerList.size() << ") is sufficient.";
|
||||
cLog(lsINFO) << "Node count (" << peerList.size() << ") is sufficient.";
|
||||
}
|
||||
|
||||
if (mConsensus)
|
||||
@@ -443,7 +443,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
// check if the ledger is good enough to go to omFULL
|
||||
// Note: Do not go to omFULL if we don't have the previous ledger
|
||||
// check if the ledger is bad enough to go to omCONNECTED -- TODO
|
||||
if (theApp->getOPs().getNetworkTimeNC() < theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC())
|
||||
if (theApp->getOPs().getNetworkTimeNC() < mLedgerMaster->getCurrentLedger()->getCloseTimeNC())
|
||||
setMode(omFULL);
|
||||
}
|
||||
|
||||
@@ -454,7 +454,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
}
|
||||
|
||||
if ((!mConsensus) && (mMode != omDISCONNECTED))
|
||||
beginConsensus(networkClosed, theApp->getMasterLedger().getCurrentLedger());
|
||||
beginConsensus(networkClosed, mLedgerMaster->getCurrentLedger());
|
||||
if (mConsensus)
|
||||
mConsensus->timerEntry();
|
||||
}
|
||||
@@ -467,7 +467,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
|
||||
// FIXME: We may have a ledger with many recent validations but that no directly-connected
|
||||
// node is using. THis is kind of fundamental.
|
||||
Log(lsTRACE) << "NetworkOPs::checkLastClosedLedger";
|
||||
cLog(lsTRACE) << "NetworkOPs::checkLastClosedLedger";
|
||||
|
||||
Ledger::pointer ourClosed = mLedgerMaster->getClosedLedger();
|
||||
if(!ourClosed) return(false);
|
||||
@@ -503,7 +503,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
{
|
||||
if (!it)
|
||||
{
|
||||
Log(lsDEBUG) << "NOP::CS Dead pointer in peer list";
|
||||
cLog(lsDEBUG) << "NOP::CS Dead pointer in peer list";
|
||||
}
|
||||
else if (it->isConnected())
|
||||
{
|
||||
@@ -525,14 +525,13 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
for (boost::unordered_map<uint256, ValidationCount>::iterator it = ledgers.begin(), end = ledgers.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
Log(lsTRACE) << "L: " << it->first << " t=" << it->second.trustedValidations <<
|
||||
cLog(lsTRACE) << "L: " << it->first << " t=" << it->second.trustedValidations <<
|
||||
", n=" << it->second.nodesUsing;
|
||||
|
||||
// Temporary logging to make sure tiebreaking isn't broken
|
||||
if (it->second.trustedValidations > 0)
|
||||
Log(lsTRACE) << " TieBreakTV: " << it->second.highValidation;
|
||||
else if (it->second.nodesUsing > 0)
|
||||
Log(lsTRACE) << " TieBreakNU: " << it->second.highNodeUsing;
|
||||
cLog(lsTRACE) << " TieBreakTV: " << it->second.highValidation;
|
||||
else tLog(it->second.nodesUsing > 0, lsTRACE) << " TieBreakNU: " << it->second.highNodeUsing;
|
||||
|
||||
if (it->second > bestVC)
|
||||
{
|
||||
@@ -544,7 +543,7 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
|
||||
if (switchLedgers && (closedLedger == prevClosedLedger))
|
||||
{ // don't switch to our own previous ledger
|
||||
Log(lsINFO) << "We won't switch to our own previous ledger";
|
||||
cLog(lsINFO) << "We won't switch to our own previous ledger";
|
||||
networkClosed = ourClosed->getHash();
|
||||
switchLedgers = false;
|
||||
}
|
||||
@@ -562,22 +561,22 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
return false;
|
||||
}
|
||||
|
||||
Log(lsWARNING) << "We are not running on the consensus ledger";
|
||||
Log(lsINFO) << "Our LCL " << ourClosed->getHash();
|
||||
Log(lsINFO) << "Net LCL " << closedLedger;
|
||||
cLog(lsWARNING) << "We are not running on the consensus ledger";
|
||||
cLog(lsINFO) << "Our LCL " << ourClosed->getHash();
|
||||
cLog(lsINFO) << "Net LCL " << closedLedger;
|
||||
if ((mMode == omTRACKING) || (mMode == omFULL))
|
||||
setMode(omCONNECTED);
|
||||
|
||||
Ledger::pointer consensus = mLedgerMaster->getLedgerByHash(closedLedger);
|
||||
if (!consensus)
|
||||
{
|
||||
Log(lsINFO) << "Acquiring consensus ledger " << closedLedger;
|
||||
cLog(lsINFO) << "Acquiring consensus ledger " << closedLedger;
|
||||
if (!mAcquiringLedger || (mAcquiringLedger->getHash() != closedLedger))
|
||||
mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(closedLedger);
|
||||
if (!mAcquiringLedger || mAcquiringLedger->isFailed())
|
||||
{
|
||||
theApp->getMasterLedgerAcquire().dropLedger(closedLedger);
|
||||
Log(lsERROR) << "Network ledger cannot be acquired";
|
||||
cLog(lsERROR) << "Network ledger cannot be acquired";
|
||||
return true;
|
||||
}
|
||||
if (!mAcquiringLedger->isComplete())
|
||||
@@ -614,9 +613,9 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool duringCo
|
||||
{ // set the newledger as our last closed ledger -- this is abnormal code
|
||||
|
||||
if (duringConsensus)
|
||||
Log(lsERROR) << "JUMPdc last closed ledger to " << newLedger->getHash();
|
||||
cLog(lsERROR) << "JUMPdc last closed ledger to " << newLedger->getHash();
|
||||
else
|
||||
Log(lsERROR) << "JUMP last closed ledger to " << newLedger->getHash();
|
||||
cLog(lsERROR) << "JUMP last closed ledger to " << newLedger->getHash();
|
||||
|
||||
newLedger->setClosed();
|
||||
Ledger::pointer openLedger = boost::make_shared<Ledger>(false, boost::ref(*newLedger));
|
||||
@@ -636,13 +635,13 @@ void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool duringCo
|
||||
|
||||
int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer closingLedger)
|
||||
{
|
||||
Log(lsINFO) << "Consensus time for ledger " << closingLedger->getLedgerSeq();
|
||||
Log(lsINFO) << " LCL is " << closingLedger->getParentHash();
|
||||
cLog(lsINFO) << "Consensus time for ledger " << closingLedger->getLedgerSeq();
|
||||
cLog(lsINFO) << " LCL is " << closingLedger->getParentHash();
|
||||
|
||||
Ledger::pointer prevLedger = mLedgerMaster->getLedgerByHash(closingLedger->getParentHash());
|
||||
if (!prevLedger)
|
||||
{ // this shouldn't happen unless we jump ledgers
|
||||
Log(lsWARNING) << "Don't have LCL, going to tracking";
|
||||
cLog(lsWARNING) << "Don't have LCL, going to tracking";
|
||||
setMode(omTRACKING);
|
||||
return 3;
|
||||
}
|
||||
@@ -653,10 +652,10 @@ int NetworkOPs::beginConsensus(const uint256& networkClosed, Ledger::pointer clo
|
||||
assert(!mConsensus);
|
||||
prevLedger->setImmutable();
|
||||
mConsensus = boost::make_shared<LedgerConsensus>(
|
||||
networkClosed, prevLedger, theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC());
|
||||
networkClosed, prevLedger, mLedgerMaster->getCurrentLedger()->getCloseTimeNC());
|
||||
mConsensus->swapDefer(mDeferredProposals);
|
||||
|
||||
Log(lsDEBUG) << "Initiating consensus engine";
|
||||
cLog(lsDEBUG) << "Initiating consensus engine";
|
||||
return mConsensus->startup();
|
||||
}
|
||||
|
||||
@@ -672,8 +671,8 @@ bool NetworkOPs::haveConsensusObject()
|
||||
bool ledgerChange = checkLastClosedLedger(peerList, networkClosed);
|
||||
if (!ledgerChange)
|
||||
{
|
||||
Log(lsWARNING) << "Beginning consensus due to peer action";
|
||||
beginConsensus(networkClosed, theApp->getMasterLedger().getCurrentLedger());
|
||||
cLog(lsWARNING) << "Beginning consensus due to peer action";
|
||||
beginConsensus(networkClosed, mLedgerMaster->getCurrentLedger());
|
||||
}
|
||||
return mConsensus;
|
||||
}
|
||||
@@ -702,14 +701,14 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, cons
|
||||
|
||||
if (!haveConsensusObject())
|
||||
{
|
||||
Log(lsINFO) << "Received proposal outside consensus window";
|
||||
cLog(lsINFO) << "Received proposal outside consensus window";
|
||||
return mMode != omFULL;
|
||||
}
|
||||
|
||||
// Is this node on our UNL?
|
||||
if (!theApp->getUNL().nodeInUNL(naPeerPublic))
|
||||
{
|
||||
Log(lsINFO) << "Untrusted proposal: " << naPeerPublic.humanNodePublic() << " " << proposeHash;
|
||||
cLog(lsINFO) << "Untrusted proposal: " << naPeerPublic.humanNodePublic() << " " << proposeHash;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -719,7 +718,7 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, cons
|
||||
boost::make_shared<LedgerProposal>(prevLedger, proposeSeq, proposeHash, closeTime, naPeerPublic);
|
||||
if (!proposal->checkSign(signature))
|
||||
{
|
||||
Log(lsWARNING) << "New-style ledger proposal fails signature check";
|
||||
cLog(lsWARNING) << "New-style ledger proposal fails signature check";
|
||||
return false;
|
||||
}
|
||||
if (prevLedger == mConsensus->getLCL())
|
||||
@@ -732,7 +731,7 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, cons
|
||||
boost::make_shared<LedgerProposal>(mConsensus->getLCL(), proposeSeq, proposeHash, closeTime, naPeerPublic);
|
||||
if (!proposal->checkSign(signature))
|
||||
{ // Note that if the LCL is different, the signature check will fail
|
||||
Log(lsWARNING) << "Ledger proposal fails signature check";
|
||||
cLog(lsWARNING) << "Ledger proposal fails signature check";
|
||||
proposal->setSignature(signature);
|
||||
mConsensus->deferProposal(proposal, nodePublic);
|
||||
return false;
|
||||
@@ -759,7 +758,7 @@ bool NetworkOPs::hasTXSet(const boost::shared_ptr<Peer>& peer, const uint256& se
|
||||
{
|
||||
if (!haveConsensusObject())
|
||||
{
|
||||
Log(lsINFO) << "Peer has TX set, not during consensus";
|
||||
cLog(lsINFO) << "Peer has TX set, not during consensus";
|
||||
return false;
|
||||
}
|
||||
return mConsensus->peerHasSet(peer, set, status);
|
||||
@@ -773,12 +772,12 @@ void NetworkOPs::mapComplete(const uint256& hash, SHAMap::ref map)
|
||||
|
||||
void NetworkOPs::endConsensus(bool correctLCL)
|
||||
{
|
||||
uint256 deadLedger = theApp->getMasterLedger().getClosedLedger()->getParentHash();
|
||||
uint256 deadLedger = mLedgerMaster->getClosedLedger()->getParentHash();
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
BOOST_FOREACH(Peer::ref it, peerList)
|
||||
if (it && (it->getClosedLedgerHash() == deadLedger))
|
||||
{
|
||||
Log(lsTRACE) << "Killing obsolete peer status";
|
||||
cLog(lsTRACE) << "Killing obsolete peer status";
|
||||
it->cycleStatus();
|
||||
}
|
||||
mConsensus->swapDefer(mDeferredProposals);
|
||||
@@ -853,7 +852,7 @@ std::vector<NewcoinAddress>
|
||||
|
||||
bool NetworkOPs::recvValidation(const SerializedValidation::pointer& val)
|
||||
{
|
||||
Log(lsINFO) << "recvValidation " << val->getLedgerHash();
|
||||
cLog(lsINFO) << "recvValidation " << val->getLedgerHash();
|
||||
return theApp->getValidations().addValidation(val);
|
||||
}
|
||||
|
||||
@@ -1225,6 +1224,12 @@ void NetworkOPs::newLCL(int proposers, int convergeTime, const uint256& ledgerHa
|
||||
mLastCloseHash = ledgerHash;
|
||||
}
|
||||
|
||||
uint32 NetworkOPs::acceptLedger()
|
||||
{ // accept the current transaction tree, return the new ledger's sequence
|
||||
beginConsensus(mLedgerMaster->getClosedLedger()->getHash(), mLedgerMaster->getCurrentLedger());
|
||||
mConsensus->simulate();
|
||||
return mLedgerMaster->getCurrentLedger()->getLedgerSeq();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void NetworkOPs::subAccountChanges(InfoSub* ispListener, const uint256 uLedgerHash)
|
||||
|
||||
@@ -190,6 +190,7 @@ public:
|
||||
uint32 getLastCloseTime() { return mLastCloseTime; }
|
||||
void setLastCloseTime(uint32 t) { mLastCloseTime = t; }
|
||||
Json::Value getServerInfo();
|
||||
uint32 acceptLedger();
|
||||
|
||||
// client information retrieval functions
|
||||
std::vector< std::pair<uint32, uint256> >
|
||||
|
||||
107
src/Peer.cpp
107
src/Peer.cpp
@@ -16,6 +16,8 @@
|
||||
#include "utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
// Don't try to run past receiving nonsense from a peer
|
||||
#define TRUST_NETWORK
|
||||
|
||||
@@ -28,7 +30,7 @@ Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
|
||||
mSocketSsl(io_service, ctx),
|
||||
mVerifyTimer(io_service)
|
||||
{
|
||||
// Log(lsDEBUG) << "CREATING PEER: " << ADDRESS(this);
|
||||
// cLog(lsDEBUG) << "CREATING PEER: " << ADDRESS(this);
|
||||
}
|
||||
|
||||
void Peer::handle_write(const boost::system::error_code& error, size_t bytes_transferred)
|
||||
@@ -47,7 +49,7 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
Log(lsINFO) << "Peer: Write: Error: " << ADDRESS(this) << ": bytes=" << bytes_transferred << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Write: Error: " << ADDRESS(this) << ": bytes=" << bytes_transferred << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
|
||||
detach("hw");
|
||||
}
|
||||
@@ -67,7 +69,7 @@ void Peer::setIpPort(const std::string& strIP, int iPort)
|
||||
{
|
||||
mIpPort = make_pair(strIP, iPort);
|
||||
|
||||
Log(lsDEBUG) << "Peer: Set: "
|
||||
cLog(lsDEBUG) << "Peer: Set: "
|
||||
<< ADDRESS(this) << "> "
|
||||
<< (mNodePublic.isValid() ? mNodePublic.humanNodePublic() : "-") << " " << getIP() << " " << getPort();
|
||||
}
|
||||
@@ -78,7 +80,7 @@ void Peer::detach(const char *rsn)
|
||||
{
|
||||
mDetaching = true; // Race is ok.
|
||||
/*
|
||||
Log(lsDEBUG) << "Peer: Detach: "
|
||||
cLog(lsDEBUG) << "Peer: Detach: "
|
||||
<< ADDRESS(this) << "> "
|
||||
<< rsn << ": "
|
||||
<< (mNodePublic.isValid() ? mNodePublic.humanNodePublic() : "-") << " " << getIP() << " " << getPort();
|
||||
@@ -105,7 +107,7 @@ void Peer::detach(const char *rsn)
|
||||
mIpPort.first.clear(); // Be idempotent.
|
||||
}
|
||||
/*
|
||||
Log(lsDEBUG) << "Peer: Detach: "
|
||||
cLog(lsDEBUG) << "Peer: Detach: "
|
||||
<< ADDRESS(this) << "< "
|
||||
<< rsn << ": "
|
||||
<< (mNodePublic.isValid() ? mNodePublic.humanNodePublic() : "-") << " " << getIP() << " " << getPort();
|
||||
@@ -124,14 +126,14 @@ void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
|
||||
}
|
||||
else if (ecResult)
|
||||
{
|
||||
Log(lsINFO) << "Peer verify timer error";
|
||||
cLog(lsINFO) << "Peer verify timer error";
|
||||
|
||||
// Can't do anything sound.
|
||||
abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Log(lsINFO) << "Peer: Verify: Peer failed to verify in time.";
|
||||
//cLog(lsINFO) << "Peer: Verify: Peer failed to verify in time.";
|
||||
|
||||
detach("hvt");
|
||||
}
|
||||
@@ -157,7 +159,7 @@ void Peer::connect(const std::string& strIp, int iPort)
|
||||
|
||||
if (err || itrEndpoint == boost::asio::ip::tcp::resolver::iterator())
|
||||
{
|
||||
Log(lsWARNING) << "Peer: Connect: Bad IP: " << strIp;
|
||||
cLog(lsWARNING) << "Peer: Connect: Bad IP: " << strIp;
|
||||
detach("c");
|
||||
return;
|
||||
}
|
||||
@@ -168,7 +170,7 @@ void Peer::connect(const std::string& strIp, int iPort)
|
||||
|
||||
if (err)
|
||||
{
|
||||
Log(lsWARNING) << "Peer: Connect: Failed to set timer.";
|
||||
cLog(lsWARNING) << "Peer: Connect: Failed to set timer.";
|
||||
detach("c2");
|
||||
return;
|
||||
}
|
||||
@@ -176,7 +178,7 @@ void Peer::connect(const std::string& strIp, int iPort)
|
||||
|
||||
if (!err)
|
||||
{
|
||||
Log(lsINFO) << "Peer: Connect: Outbound: " << ADDRESS(this) << ": " << mIpPort.first << " " << mIpPort.second;
|
||||
cLog(lsINFO) << "Peer: Connect: Outbound: " << ADDRESS(this) << ": " << mIpPort.first << " " << mIpPort.second;
|
||||
|
||||
boost::asio::async_connect(
|
||||
getSocket(),
|
||||
@@ -197,7 +199,7 @@ void Peer::handleStart(const boost::system::error_code& error)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
Log(lsINFO) << "Peer: Handshake: Error: " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Handshake: Error: " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
detach("hs");
|
||||
}
|
||||
else
|
||||
@@ -212,7 +214,7 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
Log(lsINFO) << "Peer: Connect: Error: " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Connect: Error: " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
detach("hc");
|
||||
}
|
||||
else
|
||||
@@ -244,7 +246,7 @@ void Peer::connected(const boost::system::error_code& error)
|
||||
{
|
||||
// Not redundant ip and port, handshake, and start.
|
||||
|
||||
Log(lsINFO) << "Peer: Inbound: Accepted: " << ADDRESS(this) << ": " << strIp << " " << iPort;
|
||||
cLog(lsINFO) << "Peer: Inbound: Accepted: " << ADDRESS(this) << ": " << strIp << " " << iPort;
|
||||
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||
|
||||
@@ -253,7 +255,7 @@ void Peer::connected(const boost::system::error_code& error)
|
||||
}
|
||||
else if (!mDetaching)
|
||||
{
|
||||
Log(lsINFO) << "Peer: Inbound: Error: " << ADDRESS(this) << ": " << strIp << " " << iPort << " : " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Inbound: Error: " << ADDRESS(this) << ": " << strIp << " " << iPort << " : " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
|
||||
detach("ctd");
|
||||
}
|
||||
@@ -334,7 +336,7 @@ void Peer::handle_read_header(const boost::system::error_code& error)
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "Peer: Header: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Header: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
detach("hrh2");
|
||||
}
|
||||
}
|
||||
@@ -353,7 +355,7 @@ void Peer::handle_read_body(const boost::system::error_code& error)
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "Peer: Body: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
cLog(lsINFO) << "Peer: Body: Error: " << ADDRESS(this) << ": " << error.category().name() << ": " << error.message() << ": " << error;
|
||||
detach("hrb");
|
||||
}
|
||||
}
|
||||
@@ -370,7 +372,7 @@ void Peer::processReadBuffer()
|
||||
// If connected and get a mtHELLO or if not connected and get a non-mtHELLO, wrong message was sent.
|
||||
if (mHelloed == (type == newcoin::mtHELLO))
|
||||
{
|
||||
Log(lsWARNING) << "Wrong message type: " << type;
|
||||
cLog(lsWARNING) << "Wrong message type: " << type;
|
||||
detach("prb1");
|
||||
}
|
||||
else
|
||||
@@ -579,36 +581,40 @@ void Peer::recvHello(newcoin::TMHello& packet)
|
||||
{
|
||||
int64 to = ourTime;
|
||||
to -= packet.nettime();
|
||||
Log(lsDEBUG) << "Connect: time offset " << to;
|
||||
cLog(lsDEBUG) << "Connect: time offset " << to;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (packet.has_nettime() && ((packet.nettime() < minTime) || (packet.nettime() > maxTime)))
|
||||
{
|
||||
if (packet.nettime() > maxTime)
|
||||
Log(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off +" << packet.nettime() - ourTime;
|
||||
{
|
||||
cLog(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off +" << packet.nettime() - ourTime;
|
||||
}
|
||||
else if(packet.nettime() < minTime)
|
||||
Log(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off -" << ourTime - packet.nettime();
|
||||
{
|
||||
cLog(lsINFO) << "Recv(Hello): " << getIP() << " :Clock far off -" << ourTime - packet.nettime();
|
||||
}
|
||||
}
|
||||
else if (packet.protoversionmin() < MAKE_VERSION_INT(MIN_PROTO_MAJOR, MIN_PROTO_MINOR))
|
||||
{
|
||||
Log(lsINFO) << "Recv(Hello): Server requires protocol version " <<
|
||||
cLog(lsINFO) << "Recv(Hello): Server requires protocol version " <<
|
||||
GET_VERSION_MAJOR(packet.protoversion()) << "." << GET_VERSION_MINOR(packet.protoversion())
|
||||
<< " we run " << PROTO_VERSION_MAJOR << "." << PROTO_VERSION_MINOR;
|
||||
}
|
||||
else if (!mNodePublic.setNodePublic(packet.nodepublic()))
|
||||
{
|
||||
Log(lsINFO) << "Recv(Hello): Disconnect: Bad node public key.";
|
||||
cLog(lsINFO) << "Recv(Hello): Disconnect: Bad node public key.";
|
||||
}
|
||||
else if (!mNodePublic.verifyNodePublic(mCookieHash, packet.nodeproof()))
|
||||
{ // Unable to verify they have private key for claimed public key.
|
||||
Log(lsINFO) << "Recv(Hello): Disconnect: Failed to verify session.";
|
||||
cLog(lsINFO) << "Recv(Hello): Disconnect: Failed to verify session.";
|
||||
}
|
||||
else
|
||||
{ // Successful connection.
|
||||
Log(lsINFO) << "Recv(Hello): Connect: " << mNodePublic.humanNodePublic();
|
||||
if (packet.protoversion() != MAKE_VERSION_INT(PROTO_VERSION_MAJOR, PROTO_VERSION_MINOR))
|
||||
Log(lsINFO) << "Peer speaks version " <<
|
||||
cLog(lsINFO) << "Recv(Hello): Connect: " << mNodePublic.humanNodePublic();
|
||||
tLog(packet.protoversion() != MAKE_VERSION_INT(PROTO_VERSION_MAJOR, PROTO_VERSION_MINOR), lsINFO)
|
||||
<< "Peer speaks version " <<
|
||||
(packet.protoversion() >> 16) << "." << (packet.protoversion() & 0xFF);
|
||||
mHello = packet;
|
||||
|
||||
@@ -620,7 +626,7 @@ void Peer::recvHello(newcoin::TMHello& packet)
|
||||
|
||||
if (!theApp->getConnectionPool().peerConnected(shared_from_this(), mNodePublic, getIP(), getPort()))
|
||||
{ // Already connected, self, or some other reason.
|
||||
Log(lsINFO) << "Recv(Hello): Disconnect: Extraneous connection.";
|
||||
cLog(lsINFO) << "Recv(Hello): Disconnect: Extraneous connection.";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -716,7 +722,7 @@ void Peer::recvPropose(newcoin::TMProposeSet& packet)
|
||||
if ((packet.currenttxhash().size() != 32) || (packet.nodepubkey().size() < 28) ||
|
||||
(packet.signature().size() < 56))
|
||||
{
|
||||
Log(lsWARNING) << "Received proposal is malformed";
|
||||
cLog(lsWARNING) << "Received proposal is malformed";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -756,7 +762,7 @@ void Peer::recvValidation(newcoin::TMValidation& packet)
|
||||
{
|
||||
if (packet.validation().size() < 50)
|
||||
{
|
||||
Log(lsWARNING) << "Too small validation from peer";
|
||||
cLog(lsWARNING) << "Too small validation from peer";
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
return;
|
||||
}
|
||||
@@ -774,13 +780,13 @@ void Peer::recvValidation(newcoin::TMValidation& packet)
|
||||
uint256 signingHash = val->getSigningHash();
|
||||
if (!theApp->isNew(signingHash))
|
||||
{
|
||||
Log(lsTRACE) << "Validation is duplicate";
|
||||
cLog(lsTRACE) << "Validation is duplicate";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!val->isValid(signingHash))
|
||||
{
|
||||
Log(lsWARNING) << "Validation is invalid";
|
||||
cLog(lsWARNING) << "Validation is invalid";
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
return;
|
||||
}
|
||||
@@ -794,7 +800,7 @@ void Peer::recvValidation(newcoin::TMValidation& packet)
|
||||
//#ifndef TRUST_NETWORK
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << "Exception processing validation";
|
||||
cLog(lsWARNING) << "Exception processing validation";
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
}
|
||||
//#endif
|
||||
@@ -837,7 +843,7 @@ void Peer::recvGetPeers(newcoin::TMGetPeers& packet)
|
||||
addr->set_ipv4(inet_addr(strIP.c_str()));
|
||||
addr->set_ipv4port(iPort);
|
||||
|
||||
//Log(lsINFO) << "Peer: Teaching: " << ADDRESS(this) << ": " << n << ": " << strIP << " " << iPort;
|
||||
//cLog(lsINFO) << "Peer: Teaching: " << ADDRESS(this) << ": " << n << ": " << strIP << " " << iPort;
|
||||
}
|
||||
|
||||
PackedMessage::pointer message = boost::make_shared<PackedMessage>(peers, newcoin::mtPEERS);
|
||||
@@ -859,7 +865,7 @@ void Peer::recvPeers(newcoin::TMPeers& packet)
|
||||
|
||||
if (strIP != "0.0.0.0" && strIP != "127.0.0.1")
|
||||
{
|
||||
//Log(lsINFO) << "Peer: Learning: " << ADDRESS(this) << ": " << i << ": " << strIP << " " << iPort;
|
||||
//cLog(lsINFO) << "Peer: Learning: " << ADDRESS(this) << ": " << i << ": " << strIP << " " << iPort;
|
||||
|
||||
theApp->getConnectionPool().savePeer(strIP, iPort, UniqueNodeList::vsTold);
|
||||
}
|
||||
@@ -900,7 +906,7 @@ void Peer::recvAccount(newcoin::TMAccount& packet)
|
||||
|
||||
void Peer::recvStatus(newcoin::TMStatusChange& packet)
|
||||
{
|
||||
Log(lsTRACE) << "Received status change from peer " << getIP();
|
||||
cLog(lsTRACE) << "Received status change from peer " << getIP();
|
||||
if (!packet.has_networktime())
|
||||
packet.set_networktime(theApp->getOPs().getNetworkTimeNC());
|
||||
|
||||
@@ -917,7 +923,7 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet)
|
||||
{
|
||||
if (!mClosedLedgerHash.isZero())
|
||||
{
|
||||
Log(lsTRACE) << "peer has lost sync " << getIP();
|
||||
cLog(lsTRACE) << "peer has lost sync " << getIP();
|
||||
mClosedLedgerHash.zero();
|
||||
}
|
||||
mPreviousLedgerHash.zero();
|
||||
@@ -927,11 +933,11 @@ void Peer::recvStatus(newcoin::TMStatusChange& packet)
|
||||
{ // a peer has changed ledgers
|
||||
memcpy(mClosedLedgerHash.begin(), packet.ledgerhash().data(), 256 / 8);
|
||||
addLedger(mClosedLedgerHash);
|
||||
Log(lsTRACE) << "peer LCL is " << mClosedLedgerHash << " " << getIP();
|
||||
cLog(lsTRACE) << "peer LCL is " << mClosedLedgerHash << " " << getIP();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "peer has no ledger hash" << getIP();
|
||||
cLog(lsTRACE) << "peer has no ledger hash" << getIP();
|
||||
mClosedLedgerHash.zero();
|
||||
}
|
||||
|
||||
@@ -951,7 +957,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
|
||||
if (packet.itype() == newcoin::liTS_CANDIDATE)
|
||||
{ // Request is for a transaction candidate set
|
||||
Log(lsINFO) << "Received request for TX candidate set data " << getIP();
|
||||
cLog(lsINFO) << "Received request for TX candidate set data " << getIP();
|
||||
if ((!packet.has_ledgerhash() || packet.ledgerhash().size() != 32))
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
@@ -962,7 +968,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
map = theApp->getOPs().getTXMap(txHash);
|
||||
if (!map)
|
||||
{
|
||||
Log(lsERROR) << "We do not have the map our peer wants";
|
||||
cLog(lsERROR) << "We do not have the map our peer wants";
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
@@ -974,7 +980,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
}
|
||||
else
|
||||
{ // Figure out what ledger they want
|
||||
Log(lsINFO) << "Received request for ledger data " << getIP();
|
||||
cLog(lsINFO) << "Received request for ledger data " << getIP();
|
||||
Ledger::pointer ledger;
|
||||
if (packet.has_ledgerhash())
|
||||
{
|
||||
@@ -982,13 +988,12 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
if (packet.ledgerhash().size() != 32)
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
Log(lsWARNING) << "Invalid request";
|
||||
cLog(lsWARNING) << "Invalid request";
|
||||
return;
|
||||
}
|
||||
memcpy(ledgerhash.begin(), packet.ledgerhash().data(), 32);
|
||||
ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
||||
if (!ledger)
|
||||
Log(lsINFO) << "Don't have ledger " << ledgerhash;
|
||||
tLog(!ledger, lsINFO) << "Don't have ledger " << ledgerhash;
|
||||
}
|
||||
else if (packet.has_ledgerseq())
|
||||
ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq());
|
||||
@@ -1003,14 +1008,14 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
else
|
||||
{
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
Log(lsWARNING) << "Can't figure out what ledger they want";
|
||||
cLog(lsWARNING) << "Can't figure out what ledger they want";
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!ledger) || (packet.has_ledgerseq() && (packet.ledgerseq() != ledger->getLedgerSeq())))
|
||||
{
|
||||
punishPeer(PP_UNKNOWN_REQUEST);
|
||||
Log(lsWARNING) << "Can't find the ledger they want";
|
||||
cLog(lsWARNING) << "Can't find the ledger they want";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1022,14 +1027,14 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
|
||||
if(packet.itype() == newcoin::liBASE)
|
||||
{ // they want the ledger base data
|
||||
Log(lsTRACE) << "Want ledger base data";
|
||||
cLog(lsTRACE) << "Want ledger base data";
|
||||
Serializer nData(128);
|
||||
ledger->addRaw(nData);
|
||||
reply.add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
|
||||
|
||||
if (packet.nodeids().size() != 0)
|
||||
{ // new-style root request
|
||||
Log(lsINFO) << "Ledger root w/map roots request";
|
||||
cLog(lsINFO) << "Ledger root w/map roots request";
|
||||
SHAMap::pointer map = ledger->peekAccountStateMap();
|
||||
if (map)
|
||||
{ // return account state root node if possible
|
||||
@@ -1063,7 +1068,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
|
||||
if ((!map) || (packet.nodeids_size() == 0))
|
||||
{
|
||||
Log(lsWARNING) << "Can't find map or empty request";
|
||||
cLog(lsWARNING) << "Can't find map or empty request";
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
@@ -1128,7 +1133,7 @@ void Peer::recvLedger(newcoin::TMLedgerData& packet)
|
||||
const newcoin::TMLedgerNode& node = packet.nodes(i);
|
||||
if (!node.has_nodeid() || !node.has_nodedata() || (node.nodeid().size() != 33))
|
||||
{
|
||||
Log(lsWARNING) << "LedgerData request with invalid node ID";
|
||||
cLog(lsWARNING) << "LedgerData request with invalid node ID";
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
@@ -1288,7 +1293,7 @@ Json::Value Peer::getJson()
|
||||
case newcoin::nsMONITORING: ret["status"] = "monitoring"; break;
|
||||
case newcoin::nsVALIDATING: ret["status"] = "validating"; break;
|
||||
case newcoin::nsSHUTTING: ret["status"] = "shutting"; break;
|
||||
default: Log(lsWARNING) << "Peer has unknown status: " << mLastStatus.newstatus();
|
||||
default: cLog(lsWARNING) << "Peer has unknown status: " << mLastStatus.newstatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
#include "../json/reader.h"
|
||||
#include "../json/writer.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork)
|
||||
: mNetOps(nopNetwork), mSocket(io_service)
|
||||
{
|
||||
mRole=GUEST;
|
||||
mRole = GUEST;
|
||||
}
|
||||
|
||||
Json::Value RPCServer::RPCError(int iError)
|
||||
@@ -68,6 +70,7 @@ Json::Value RPCServer::RPCError(int iError)
|
||||
{ rpcNO_GEN_DECRPYT, "noGenDectypt", "Password failed to decrypt master public generator." },
|
||||
{ rpcNO_NETWORK, "noNetwork", "Network not available." },
|
||||
{ rpcNO_PERMISSION, "noPermission", "You don't have permission for this command." },
|
||||
{ rpcNOT_STANDALONE, "notStandAlone", "Operation valid in debug mode only." },
|
||||
{ rpcPASSWD_CHANGED, "passwdChanged", "Wrong key, password changed." },
|
||||
{ rpcPAYS_ACT_MALFORMED, "paysActMalformed", "Pays account malformed." },
|
||||
{ rpcPAYS_AMT_MALFORMED, "paysAmtMalformed", "Pays amount malformed." },
|
||||
@@ -175,13 +178,12 @@ std::string RPCServer::handleRequest(const std::string& requestStr)
|
||||
else if (!valParams.isArray())
|
||||
return(HTTPReply(400, "parms unparseable"));
|
||||
|
||||
Json::StyledStreamWriter w;
|
||||
w.write(Log(lsTRACE).ref(), valParams);
|
||||
Json::Value result(doCommand(strMethod, valParams));
|
||||
w.write(Log(lsTRACE).ref(), result);
|
||||
cLog(lsTRACE) << valParams;
|
||||
Json::Value result = doCommand(strMethod, valParams);
|
||||
cLog(lsTRACE) << result;
|
||||
|
||||
std::string strReply = JSONRPCReply(result, Json::Value(), id);
|
||||
return( HTTPReply(200, strReply) );
|
||||
return HTTPReply(200, strReply);
|
||||
}
|
||||
|
||||
int RPCServer::getParamCount(const Json::Value& params)
|
||||
@@ -418,6 +420,16 @@ Json::Value RPCServer::accountFromString(const uint256& uLedger, NewcoinAddress&
|
||||
return Json::Value(Json::objectValue);
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doAcceptLedger(const Json::Value ¶ms)
|
||||
{
|
||||
if (!theConfig.RUN_STANDALONE)
|
||||
return RPCError(rpcNOT_STANDALONE);
|
||||
|
||||
Json::Value obj(Json::objectValue);
|
||||
obj["newLedger"] = theApp->getOPs().acceptLedger();
|
||||
return obj;
|
||||
}
|
||||
|
||||
// account_domain_set <seed> <paying_account> [<domain>]
|
||||
Json::Value RPCServer::doAccountDomainSet(const Json::Value ¶ms)
|
||||
{
|
||||
@@ -2640,6 +2652,7 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
bool mAdminRequired;
|
||||
unsigned int iOptions;
|
||||
} commandsA[] = {
|
||||
{ "accept_ledger", &RPCServer::doAcceptLedger, 0, 0, true },
|
||||
{ "account_domain_set", &RPCServer::doAccountDomainSet, 2, 3, false, optCurrent },
|
||||
{ "account_email_set", &RPCServer::doAccountEmailSet, 2, 3, false, optCurrent },
|
||||
{ "account_info", &RPCServer::doAccountInfo, 1, 2, false, optCurrent },
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
// Misc failure
|
||||
rpcLOAD_FAILED,
|
||||
rpcNO_PERMISSION,
|
||||
rpcNOT_STANDALONE,
|
||||
|
||||
// Networking
|
||||
rpcNO_CLOSED,
|
||||
@@ -128,6 +129,7 @@ private:
|
||||
|
||||
Json::Value accountFromString(const uint256& uLedger, NewcoinAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex);
|
||||
|
||||
Json::Value doAcceptLedger(const Json::Value ¶ms);
|
||||
Json::Value doAccountDomainSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountEmailSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountInfo(const Json::Value& params);
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "../json/writer.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
std::size_t hash_value(const aciSource& asValue)
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
@@ -69,7 +71,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
bDirectAdvance = !sleDirectDir;
|
||||
bDirectDirDirty = true;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: Initialize node: uDirectTip=%s uDirectEnd=%s bDirectAdvance=%d") % uDirectTip % uDirectEnd % bDirectAdvance);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: Initialize node: uDirectTip=%s uDirectEnd=%s bDirectAdvance=%d") % uDirectTip % uDirectEnd % bDirectAdvance);
|
||||
}
|
||||
|
||||
if (bDirectAdvance)
|
||||
@@ -82,13 +84,13 @@ TER RippleCalc::calcNodeAdvance(
|
||||
if (!!uDirectTip)
|
||||
{
|
||||
// Have another quality directory.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: Quality advance: uDirectTip=%s") % uDirectTip);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: Quality advance: uDirectTip=%s") % uDirectTip);
|
||||
|
||||
sleDirectDir = lesActive.entryCache(ltDIR_NODE, uDirectTip);
|
||||
}
|
||||
else if (bReverse)
|
||||
{
|
||||
Log(lsINFO) << "calcNodeAdvance: No more offers.";
|
||||
cLog(lsINFO) << "calcNodeAdvance: No more offers.";
|
||||
|
||||
uOfferIndex = 0;
|
||||
break;
|
||||
@@ -96,7 +98,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
else
|
||||
{
|
||||
// No more offers. Should be done rather than fall off end of book.
|
||||
Log(lsINFO) << "calcNodeAdvance: Unreachable: Fell off end of order book.";
|
||||
cLog(lsINFO) << "calcNodeAdvance: Unreachable: Fell off end of order book.";
|
||||
assert(false);
|
||||
|
||||
terResult = tefEXCEPTION;
|
||||
@@ -109,7 +111,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
uEntry = 0;
|
||||
bEntryAdvance = true;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: directory dirty: saOfrRate=%s") % saOfrRate);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: directory dirty: saOfrRate=%s") % saOfrRate);
|
||||
}
|
||||
|
||||
if (!bEntryAdvance)
|
||||
@@ -122,11 +124,11 @@ TER RippleCalc::calcNodeAdvance(
|
||||
saOfferFunds = lesActive.accountFunds(uOfrOwnerID, saTakerGets); // Funds left.
|
||||
bFundsDirty = false;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: directory dirty: saOfrRate=%s") % saOfrRate);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: directory dirty: saOfrRate=%s") % saOfrRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: as is"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: as is"));
|
||||
nothing();
|
||||
}
|
||||
}
|
||||
@@ -139,12 +141,12 @@ TER RippleCalc::calcNodeAdvance(
|
||||
// Do another cur directory iff bMultiQuality
|
||||
if (bMultiQuality)
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: next quality"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: next quality"));
|
||||
bDirectAdvance = true;
|
||||
}
|
||||
else if (!bReverse)
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: unreachable: ran out of offers"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: unreachable: ran out of offers"));
|
||||
assert(false); // Can't run out of offers in forward direction.
|
||||
terResult = tefEXCEPTION;
|
||||
}
|
||||
@@ -157,12 +159,12 @@ TER RippleCalc::calcNodeAdvance(
|
||||
|
||||
const aciSource asLine = boost::make_tuple(uOfrOwnerID, uCurCurrencyID, uCurIssuerID);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: uOfrOwnerID=%s") % NewcoinAddress::createHumanAccountID(uOfrOwnerID));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: uOfrOwnerID=%s") % NewcoinAddress::createHumanAccountID(uOfrOwnerID));
|
||||
|
||||
if (sleOffer->isFieldPresent(sfExpiration) && sleOffer->getFieldU32(sfExpiration) <= lesActive.getLedger()->getParentCloseTimeNC())
|
||||
{
|
||||
// Offer is expired.
|
||||
Log(lsINFO) << "calcNodeAdvance: expired offer";
|
||||
cLog(lsINFO) << "calcNodeAdvance: expired offer";
|
||||
|
||||
assert(musUnfundedFound.find(uOfferIndex) != musUnfundedFound.end()); // Verify reverse found it too.
|
||||
bEntryAdvance = true;
|
||||
@@ -177,7 +179,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
if (bFoundForward && itForward->second != uIndex)
|
||||
{
|
||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||
Log(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (forward)";
|
||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (forward)";
|
||||
|
||||
bEntryAdvance = true;
|
||||
continue;
|
||||
@@ -189,7 +191,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
if (bFoundPast && itPast->second != uIndex)
|
||||
{
|
||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||
Log(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (past)";
|
||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (past)";
|
||||
|
||||
bEntryAdvance = true;
|
||||
continue;
|
||||
@@ -201,7 +203,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
if (bFoundReverse && itReverse->second != uIndex)
|
||||
{
|
||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||
Log(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (reverse)";
|
||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (reverse)";
|
||||
|
||||
bEntryAdvance = true;
|
||||
continue;
|
||||
@@ -215,7 +217,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
if (!saOfferFunds.isPositive())
|
||||
{
|
||||
// Offer is unfunded.
|
||||
Log(lsINFO) << "calcNodeAdvance: unfunded offer";
|
||||
cLog(lsINFO) << "calcNodeAdvance: unfunded offer";
|
||||
|
||||
if (bReverse && !bFoundReverse && !bFoundPast)
|
||||
{
|
||||
@@ -233,7 +235,7 @@ TER RippleCalc::calcNodeAdvance(
|
||||
&& !bFoundReverse) // Not mentioned for pass.
|
||||
{
|
||||
// Consider source mentioned by current path state.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: remember=%s/%s/%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: remember=%s/%s/%s")
|
||||
% NewcoinAddress::createHumanAccountID(uOfrOwnerID)
|
||||
% STAmount::createHumanCurrency(uCurCurrencyID)
|
||||
% NewcoinAddress::createHumanAccountID(uCurIssuerID));
|
||||
@@ -249,11 +251,11 @@ TER RippleCalc::calcNodeAdvance(
|
||||
|
||||
if (tesSUCCESS == terResult)
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: uOfferIndex=%s") % uOfferIndex);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: uOfferIndex=%s") % uOfferIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAdvance: terResult=%s") % transToken(terResult));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAdvance: terResult=%s") % transToken(terResult));
|
||||
}
|
||||
|
||||
return terResult;
|
||||
@@ -308,7 +310,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
const STAmount saOutFeeRate = uOfrOwnerID == uCurIssuerID || uOutAccountID == uCurIssuerID // Issuer receiving or sending.
|
||||
? saOne // No fee.
|
||||
: saTransferRate; // Transfer rate of issuer.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: uOfrOwnerID=%s uOutAccountID=%s uCurIssuerID=%s saTransferRate=%s saOutFeeRate=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: uOfrOwnerID=%s uOutAccountID=%s uCurIssuerID=%s saTransferRate=%s saOutFeeRate=%s")
|
||||
% NewcoinAddress::createHumanAccountID(uOfrOwnerID)
|
||||
% NewcoinAddress::createHumanAccountID(uOutAccountID)
|
||||
% NewcoinAddress::createHumanAccountID(uCurIssuerID)
|
||||
@@ -320,14 +322,14 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
// Set initial rate.
|
||||
saRateMax = saOutFeeRate;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Set initial rate: saRateMax=%s saOutFeeRate=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Set initial rate: saRateMax=%s saOutFeeRate=%s")
|
||||
% saRateMax
|
||||
% saOutFeeRate);
|
||||
}
|
||||
else if (saRateMax < saOutFeeRate)
|
||||
{
|
||||
// Offer exceeds initial rate.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Offer exceeds initial rate: saRateMax=%s saOutFeeRate=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Offer exceeds initial rate: saRateMax=%s saOutFeeRate=%s")
|
||||
% saRateMax
|
||||
% saOutFeeRate);
|
||||
|
||||
@@ -340,14 +342,14 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
|
||||
saRateMax = saOutFeeRate;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Reducing rate: saRateMax=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Reducing rate: saRateMax=%s")
|
||||
% saRateMax);
|
||||
}
|
||||
|
||||
STAmount saOutPass = std::min(std::min(saOfferFunds, saTakerGets), saOutReq-saOutAct); // Offer maximum out - assuming no out fees.
|
||||
STAmount saOutPlusFees = STAmount::multiply(saOutPass, saOutFeeRate); // Offer out with fees.
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saOutReq=%s saOutAct=%s saTakerGets=%s saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saOutReq=%s saOutAct=%s saTakerGets=%s saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||
% saOutReq
|
||||
% saOutAct
|
||||
% saTakerGets
|
||||
@@ -362,7 +364,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
saOutPlusFees = saOfferFunds;
|
||||
saOutPass = STAmount::divide(saOutPlusFees, saOutFeeRate);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Total exceeds fees: saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: Total exceeds fees: saOutPass=%s saOutPlusFees=%s saOfferFunds=%s")
|
||||
% saOutPass
|
||||
% saOutPlusFees
|
||||
% saOfferFunds);
|
||||
@@ -373,7 +375,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
STAmount saInPassReq = STAmount::multiply(saOutPass, saOfrRate, saTakerPays);
|
||||
STAmount saInPassAct;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saInPassReq=%s saOfrRate=%s saOutPass=%s saOutPlusFees=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: saInPassReq=%s saOfrRate=%s saOutPass=%s saOutPlusFees=%s")
|
||||
% saInPassReq
|
||||
% saOfrRate
|
||||
% saOutPass
|
||||
@@ -390,7 +392,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
|
||||
saInPassAct = saInPassReq;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: account --> OFFER --> ? : saInPassAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: account --> OFFER --> ? : saInPassAct=%s")
|
||||
% saPrvDlvReq);
|
||||
}
|
||||
else
|
||||
@@ -405,7 +407,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
saInPassReq,
|
||||
saInPassAct);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer --> OFFER --> ? : saInPassAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer --> OFFER --> ? : saInPassAct=%s")
|
||||
% saInPassAct);
|
||||
}
|
||||
|
||||
@@ -418,7 +420,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
saOutPass = STAmount::divide(saInPassAct, saOfrRate, saTakerGets);
|
||||
saOutPlusFees = STAmount::multiply(saOutPass, saOutFeeRate);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: adjusted: saOutPass=%s saOutPlusFees=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: adjusted: saOutPass=%s saOutPlusFees=%s")
|
||||
% saOutPass
|
||||
% saOutPlusFees);
|
||||
}
|
||||
@@ -438,7 +440,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
||||
if (saOutPass == saTakerGets)
|
||||
{
|
||||
// Offer became unfunded.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer became unfunded."));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverRev: offer became unfunded."));
|
||||
|
||||
bEntryAdvance = true;
|
||||
}
|
||||
@@ -516,7 +518,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
||||
STAmount saInPassFees;
|
||||
STAmount saOutPassAct;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saOutFunded=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saOutFunded=%s saInFunded=%s saInTotal=%s saInSum=%s saInPassAct=%s saOutPassMax=%s")
|
||||
% saOutFunded
|
||||
% saInFunded
|
||||
% saInTotal
|
||||
@@ -538,7 +540,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
||||
|
||||
saOutPassAct = saOutPassMax;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> account: saOutPassAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: ? --> OFFER --> account: saOutPassAct=%s")
|
||||
% saOutPassAct);
|
||||
}
|
||||
else
|
||||
@@ -564,7 +566,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
||||
saInPassFees = STAmount::multiply(saInFunded, saInFeeRate)-saInPassAct;
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saTakerGets=%s saTakerPays=%s saInPassAct=%s saOutPassAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeDeliverFwd: saTakerGets=%s saTakerPays=%s saInPassAct=%s saOutPassAct=%s")
|
||||
% saTakerGets.getFullText()
|
||||
% saTakerPays.getFullText()
|
||||
% saInPassAct.getFullText()
|
||||
@@ -696,7 +698,7 @@ void RippleCalc::calcNodeRipple(
|
||||
STAmount& saCurAct, // <-> out limit achieved.
|
||||
uint64& uRateMax)
|
||||
{
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
|
||||
% uQualityIn
|
||||
% uQualityOut
|
||||
% saPrvReq.getFullText()
|
||||
@@ -711,7 +713,7 @@ void RippleCalc::calcNodeRipple(
|
||||
const STAmount saCur = saCurReq-saCurAct;
|
||||
|
||||
#if 0
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s")
|
||||
% bPrvUnlimited
|
||||
% saPrv.getFullText()
|
||||
% saCur.getFullText());
|
||||
@@ -720,7 +722,7 @@ void RippleCalc::calcNodeRipple(
|
||||
if (uQualityIn >= uQualityOut)
|
||||
{
|
||||
// No fee.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple: No fees"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple: No fees"));
|
||||
|
||||
if (!uRateMax || STAmount::uRateOne <= uRateMax)
|
||||
{
|
||||
@@ -736,7 +738,7 @@ void RippleCalc::calcNodeRipple(
|
||||
else
|
||||
{
|
||||
// Fee.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple: Fee"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple: Fee"));
|
||||
|
||||
uint64 uRate = STAmount::getRate(STAmount(uQualityIn), STAmount(uQualityOut));
|
||||
|
||||
@@ -748,19 +750,19 @@ void RippleCalc::calcNodeRipple(
|
||||
|
||||
STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, uCurrencyID, uCurIssuerID), uQualityIn, uCurrencyID, uCurIssuerID);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCurIn=%s") % bPrvUnlimited % saPrv.getFullText() % saCurIn.getFullText());
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCurIn=%s") % bPrvUnlimited % saPrv.getFullText() % saCurIn.getFullText());
|
||||
if (bPrvUnlimited || saCurIn <= saPrv)
|
||||
{
|
||||
// All of cur. Some amount of prv.
|
||||
saCurAct += saCur;
|
||||
saPrvAct += saCurIn;
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple:3c: saCurReq=%s saPrvAct=%s") % saCurReq.getFullText() % saPrvAct.getFullText());
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple:3c: saCurReq=%s saPrvAct=%s") % saCurReq.getFullText() % saPrvAct.getFullText());
|
||||
}
|
||||
else
|
||||
{
|
||||
// A part of cur. All of prv. (cur as driver)
|
||||
STAmount saCurOut = STAmount::divide(STAmount::multiply(saPrv, uQualityIn, uCurrencyID, uCurIssuerID), uQualityOut, uCurrencyID, uCurIssuerID);
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCurReq.getFullText());
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCurReq.getFullText());
|
||||
|
||||
saCurAct += saCurOut;
|
||||
saPrvAct = saPrvReq;
|
||||
@@ -771,7 +773,7 @@ void RippleCalc::calcNodeRipple(
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRipple< uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRipple< uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
|
||||
% uQualityIn
|
||||
% uQualityOut
|
||||
% saPrvReq.getFullText()
|
||||
@@ -819,7 +821,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
? lesActive.rippleOwed(uCurAccountID, uNxtAccountID, uCurrencyID)
|
||||
: STAmount(uCurrencyID, uCurAccountID);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev> uIndex=%d/%d uPrvAccountID=%s uCurAccountID=%s uNxtAccountID=%s uCurrencyID=%s uQualityIn=%d uQualityOut=%d saPrvOwed=%s saPrvLimit=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev> uIndex=%d/%d uPrvAccountID=%s uCurAccountID=%s uNxtAccountID=%s uCurrencyID=%s uQualityIn=%d uQualityOut=%d saPrvOwed=%s saPrvLimit=%s")
|
||||
% uIndex
|
||||
% uLast
|
||||
% NewcoinAddress::createHumanAccountID(uPrvAccountID)
|
||||
@@ -854,16 +856,18 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
|
||||
STAmount saCurDeliverAct(saCurDeliverReq.getCurrency(), saCurDeliverReq.getIssuer());
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saPrvRedeemReq=%s saPrvIssueReq=%s saCurRedeemReq=%s saNxtOwed=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saPrvRedeemReq=%s saPrvIssueReq=%s saCurRedeemReq=%s saNxtOwed=%s")
|
||||
% saPrvRedeemReq.getFullText()
|
||||
% saPrvIssueReq.getFullText()
|
||||
% saCurRedeemReq.getFullText()
|
||||
% saNxtOwed.getFullText());
|
||||
|
||||
Log(lsINFO) << pspCur->getJson();
|
||||
cLog(lsINFO) << pspCur->getJson();
|
||||
|
||||
assert(!saCurRedeemReq || (-saNxtOwed) >= saCurRedeemReq); // Current redeem req can't be more than IOUs on hand.
|
||||
assert(!saCurIssueReq || !saNxtOwed.isPositive() || saNxtOwed == saCurRedeemReq); // If issue req, then redeem req must consume all owed.
|
||||
assert(!saCurIssueReq // If not issuing, fine.
|
||||
|| !saNxtOwed.isNegative() // Not hold next IOUs: owed is >= 0
|
||||
|| saNxtOwed == saCurRedeemReq); // If issue req, then redeem req must consume all owed.
|
||||
|
||||
if (bPrvAccount && bNxtAccount)
|
||||
{
|
||||
@@ -882,14 +886,14 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
: pspCur->saOutReq; // Previous is an offer, no limit: redeem own IOUs.
|
||||
STAmount saCurWantedAct(saCurWantedReq.getCurrency(), saCurWantedReq.getIssuer());
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> $ : saCurWantedReq=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> $ : saCurWantedReq=%s")
|
||||
% saCurWantedReq.getFullText());
|
||||
|
||||
// Calculate redeem
|
||||
if (saPrvRedeemReq) // Previous has IOUs to redeem.
|
||||
{
|
||||
// Redeem at 1:1
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Redeem at 1:1"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Redeem at 1:1"));
|
||||
|
||||
saCurWantedAct = std::min(saPrvRedeemReq, saCurWantedReq);
|
||||
saPrvRedeemAct = saCurWantedAct;
|
||||
@@ -902,7 +906,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
&& saPrvIssueReq) // Will accept IOUs from prevous.
|
||||
{
|
||||
// Rate: quality in : 1.0
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
|
||||
|
||||
// If we previously redeemed and this has a poorer rate, this won't be included the current increment.
|
||||
calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurWantedReq, saPrvIssueAct, saCurWantedAct, uRateMax);
|
||||
@@ -923,7 +927,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
&& saPrvRedeemReq) // Previous has IOUs to redeem.
|
||||
{
|
||||
// Rate : 1.0 : quality out
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate : 1.0 : quality out"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate : 1.0 : quality out"));
|
||||
|
||||
calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvRedeemReq, saCurRedeemReq, saPrvRedeemAct, saCurRedeemAct, uRateMax);
|
||||
}
|
||||
@@ -933,7 +937,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
&& saPrvRedeemAct == saPrvRedeemReq) // Previous has no IOUs to redeem remaining.
|
||||
{
|
||||
// Rate: quality in : quality out
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : quality out"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : quality out"));
|
||||
|
||||
calcNodeRipple(uQualityIn, uQualityOut, saPrvIssueReq, saCurRedeemReq, saPrvIssueAct, saCurRedeemAct, uRateMax);
|
||||
}
|
||||
@@ -944,7 +948,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
&& saPrvRedeemAct != saPrvRedeemReq) // Did not complete redeeming previous IOUs.
|
||||
{
|
||||
// Rate : 1.0 : transfer_rate
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate : 1.0 : transfer_rate"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate : 1.0 : transfer_rate"));
|
||||
|
||||
calcNodeRipple(QUALITY_ONE, lesActive.rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct, uRateMax);
|
||||
}
|
||||
@@ -955,7 +959,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
&& saPrvRedeemReq == saPrvRedeemAct) // Previously redeemed all owed IOUs.
|
||||
{
|
||||
// Rate: quality in : 1.0
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
|
||||
|
||||
calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurIssueReq, saPrvIssueAct, saCurIssueAct, uRateMax);
|
||||
}
|
||||
@@ -966,7 +970,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
terResult = tepPATH_DRY;
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: ^|account --> ACCOUNT --> account : saCurRedeemReq=%s saCurIssueReq=%s saPrvOwed=%s saCurRedeemAct=%s saCurIssueAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: ^|account --> ACCOUNT --> account : saCurRedeemReq=%s saCurIssueReq=%s saPrvOwed=%s saCurRedeemAct=%s saCurIssueAct=%s")
|
||||
% saCurRedeemReq.getFullText()
|
||||
% saCurIssueReq.getFullText()
|
||||
% saPrvOwed.getFullText()
|
||||
@@ -978,7 +982,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
{
|
||||
// account --> ACCOUNT --> offer
|
||||
// Note: deliver is always issue as ACCOUNT is the issuer for the offer input.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> offer"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> offer"));
|
||||
|
||||
// redeem -> deliver/issue.
|
||||
if (saPrvOwed.isPositive() // Previous has IOUs to redeem.
|
||||
@@ -1002,7 +1006,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
terResult = tepPATH_DRY;
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saCurDeliverReq=%s saCurDeliverAct=%s saPrvOwed=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saCurDeliverReq=%s saCurDeliverAct=%s saPrvOwed=%s")
|
||||
% saCurDeliverReq.getFullText()
|
||||
% saCurDeliverAct.getFullText()
|
||||
% saPrvOwed.getFullText());
|
||||
@@ -1017,7 +1021,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
: pspCur->saOutReq; // Previous is an offer, no limit: redeem own IOUs.
|
||||
STAmount saCurWantedAct(saCurWantedReq.getCurrency(), saCurWantedReq.getIssuer());
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> $ : saCurWantedReq=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> $ : saCurWantedReq=%s")
|
||||
% saCurWantedReq.getFullText());
|
||||
|
||||
// Rate: quality in : 1.0
|
||||
@@ -1033,7 +1037,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
{
|
||||
// offer --> ACCOUNT --> account
|
||||
// Note: offer is always delivering(redeeming) as account is issuer.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> account"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> account"));
|
||||
|
||||
// deliver -> redeem
|
||||
if (saCurRedeemReq) // Next wants us to redeem.
|
||||
@@ -1050,7 +1054,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
calcNodeRipple(QUALITY_ONE, lesActive.rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurIssueReq, saPrvDeliverAct, saCurIssueAct, uRateMax);
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saCurRedeemReq=%s saCurIssueAct=%s saCurIssueReq=%s saPrvDeliverAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: saCurRedeemReq=%s saCurIssueAct=%s saCurIssueReq=%s saPrvDeliverAct=%s")
|
||||
% saCurRedeemReq.getFullText()
|
||||
% saCurRedeemAct.getFullText()
|
||||
% saCurIssueReq.getFullText()
|
||||
@@ -1067,7 +1071,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, const PathState::p
|
||||
{
|
||||
// offer --> ACCOUNT --> offer
|
||||
// deliver/redeem -> deliver/issue.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> offer"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> offer"));
|
||||
|
||||
// Rate : 1.0 : transfer_rate
|
||||
calcNodeRipple(QUALITY_ONE, lesActive.rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurDeliverReq, saPrvDeliverAct, saCurDeliverAct, uRateMax);
|
||||
@@ -1136,7 +1140,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
|
||||
STAmount& saCurDeliverAct = pnCur.saFwdDeliver;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd> uIndex=%d/%d saPrvRedeemReq=%s saPrvIssueReq=%s saPrvDeliverReq=%s saCurRedeemReq=%s saCurIssueReq=%s saCurDeliverReq=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd> uIndex=%d/%d saPrvRedeemReq=%s saPrvIssueReq=%s saPrvDeliverReq=%s saCurRedeemReq=%s saCurIssueReq=%s saCurDeliverReq=%s")
|
||||
% uIndex
|
||||
% uLast
|
||||
% saPrvRedeemReq.getFullText()
|
||||
@@ -1192,7 +1196,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
}
|
||||
saCurSendMaxAct += saCurIssueAct;
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: ^ --> ACCOUNT --> account : saCurSendMaxReq=%s saCurRedeemAct=%s saCurIssueReq=%s saCurIssueAct=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: ^ --> ACCOUNT --> account : saCurSendMaxReq=%s saCurRedeemAct=%s saCurIssueReq=%s saCurIssueAct=%s")
|
||||
% saCurSendMaxReq.getFullText()
|
||||
% saCurRedeemAct.getFullText()
|
||||
% saCurIssueReq.getFullText()
|
||||
@@ -1201,7 +1205,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
else if (uIndex == uLast)
|
||||
{
|
||||
// account --> ACCOUNT --> $
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s")
|
||||
% NewcoinAddress::createHumanAccountID(uPrvAccountID)
|
||||
% NewcoinAddress::createHumanAccountID(uCurAccountID)
|
||||
% saPrvRedeemReq.getFullText()
|
||||
@@ -1224,7 +1228,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
else
|
||||
{
|
||||
// account --> ACCOUNT --> account
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> account"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> account"));
|
||||
|
||||
// Previous redeem part 1: redeem -> redeem
|
||||
if (saPrvRedeemReq != saPrvRedeemAct) // Previous wants to redeem. To next must be ok.
|
||||
@@ -1267,7 +1271,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
else if (bPrvAccount && !bNxtAccount)
|
||||
{
|
||||
// account --> ACCOUNT --> offer
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> offer"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> offer"));
|
||||
|
||||
// redeem -> issue.
|
||||
// wants to redeem and current would and can issue.
|
||||
@@ -1295,7 +1299,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
if (uIndex == uLast)
|
||||
{
|
||||
// offer --> ACCOUNT --> $
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $"));
|
||||
|
||||
STAmount& saCurReceive = pspCur->saOutAct;
|
||||
|
||||
@@ -1307,7 +1311,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
else
|
||||
{
|
||||
// offer --> ACCOUNT --> account
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> account"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> account"));
|
||||
|
||||
// deliver -> redeem
|
||||
if (saPrvDeliverReq) // Previous wants to deliver.
|
||||
@@ -1333,7 +1337,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
||||
{
|
||||
// offer --> ACCOUNT --> offer
|
||||
// deliver/redeem -> deliver/issue.
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> offer"));
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> offer"));
|
||||
|
||||
if (saPrvDeliverReq // Previous wants to deliver
|
||||
&& saCurIssueReq) // Current wants issue.
|
||||
@@ -1377,7 +1381,7 @@ TER PathState::pushImply(
|
||||
const PaymentNode& pnPrv = vpnNodes.back();
|
||||
TER terResult = tesSUCCESS;
|
||||
|
||||
Log(lsINFO) << "pushImply> "
|
||||
cLog(lsINFO) << "pushImply> "
|
||||
<< NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
<< " " << STAmount::createHumanCurrency(uCurrencyID)
|
||||
<< " " << NewcoinAddress::createHumanAccountID(uIssuerID);
|
||||
@@ -1410,7 +1414,7 @@ TER PathState::pushImply(
|
||||
uIssuerID);
|
||||
}
|
||||
|
||||
Log(lsINFO) << "pushImply< " << terResult;
|
||||
cLog(lsINFO) << "pushImply< " << terResult;
|
||||
|
||||
return terResult;
|
||||
}
|
||||
@@ -1423,7 +1427,7 @@ TER PathState::pushNode(
|
||||
const uint160& uCurrencyID,
|
||||
const uint160& uIssuerID)
|
||||
{
|
||||
Log(lsINFO) << "pushNode> "
|
||||
cLog(lsINFO) << "pushNode> "
|
||||
<< NewcoinAddress::createHumanAccountID(uAccountID)
|
||||
<< " " << STAmount::createHumanCurrency(uCurrencyID)
|
||||
<< "/" << NewcoinAddress::createHumanAccountID(uIssuerID);
|
||||
@@ -1443,7 +1447,7 @@ TER PathState::pushNode(
|
||||
|
||||
if (iType & ~STPathElement::typeValidBits)
|
||||
{
|
||||
Log(lsINFO) << "pushNode: bad bits.";
|
||||
cLog(lsINFO) << "pushNode: bad bits.";
|
||||
|
||||
terResult = temBAD_PATH;
|
||||
}
|
||||
@@ -1477,7 +1481,7 @@ TER PathState::pushNode(
|
||||
|
||||
if (!sleRippleState)
|
||||
{
|
||||
Log(lsINFO) << "pushNode: No credit line between "
|
||||
cLog(lsINFO) << "pushNode: No credit line between "
|
||||
<< NewcoinAddress::createHumanAccountID(pnBck.uAccountID)
|
||||
<< " and "
|
||||
<< NewcoinAddress::createHumanAccountID(pnCur.uAccountID)
|
||||
@@ -1485,13 +1489,13 @@ TER PathState::pushNode(
|
||||
<< STAmount::createHumanCurrency(pnPrv.uCurrencyID)
|
||||
<< "." ;
|
||||
|
||||
Log(lsINFO) << getJson();
|
||||
cLog(lsINFO) << getJson();
|
||||
|
||||
terResult = terNO_LINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "pushNode: Credit line found between "
|
||||
cLog(lsINFO) << "pushNode: Credit line found between "
|
||||
<< NewcoinAddress::createHumanAccountID(pnBck.uAccountID)
|
||||
<< " and "
|
||||
<< NewcoinAddress::createHumanAccountID(pnCur.uAccountID)
|
||||
@@ -1531,7 +1535,7 @@ TER PathState::pushNode(
|
||||
vpnNodes.push_back(pnCur);
|
||||
}
|
||||
}
|
||||
Log(lsINFO) << "pushNode< " << terResult;
|
||||
cLog(lsINFO) << "pushNode< " << terResult;
|
||||
|
||||
return terResult;
|
||||
}
|
||||
@@ -1608,7 +1612,7 @@ PathState::PathState(
|
||||
else if (!umForward.insert(std::make_pair(boost::make_tuple(pnCur.uAccountID, pnCur.uCurrencyID, pnCur.uIssuerID), uIndex)).second)
|
||||
{
|
||||
// Failed to insert. Have a loop.
|
||||
Log(lsINFO) << boost::str(boost::format("PathState: loop detected: %s")
|
||||
cLog(lsINFO) << boost::str(boost::format("PathState: loop detected: %s")
|
||||
% getJson());
|
||||
|
||||
terStatus = temBAD_PATH_LOOP;
|
||||
@@ -1616,7 +1620,7 @@ PathState::PathState(
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("PathState: in=%s/%s out=%s/%s %s")
|
||||
cLog(lsINFO) << boost::str(boost::format("PathState: in=%s/%s out=%s/%s %s")
|
||||
% STAmount::createHumanCurrency(uInCurrencyID)
|
||||
% NewcoinAddress::createHumanAccountID(uInIssuerID)
|
||||
% STAmount::createHumanCurrency(uOutCurrencyID)
|
||||
@@ -1697,7 +1701,7 @@ TER RippleCalc::calcNodeFwd(const unsigned int uIndex, const PathState::pointer&
|
||||
const PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
||||
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeFwd> uIndex=%d") % uIndex);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd> uIndex=%d") % uIndex);
|
||||
|
||||
TER terResult = bCurAccount
|
||||
? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality)
|
||||
@@ -1708,7 +1712,7 @@ TER RippleCalc::calcNodeFwd(const unsigned int uIndex, const PathState::pointer&
|
||||
terResult = calcNodeFwd(uIndex+1, pspCur, bMultiQuality);
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeFwd< uIndex=%d terResult=%d") % uIndex % terResult);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd< uIndex=%d terResult=%d") % uIndex % terResult);
|
||||
|
||||
return terResult;
|
||||
}
|
||||
@@ -1734,7 +1738,7 @@ TER RippleCalc::calcNodeRev(const unsigned int uIndex, const PathState::pointer&
|
||||
|
||||
saTransferRate = STAmount::saFromRate(lesActive.rippleTransferRate(uCurIssuerID));
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRev> uIndex=%d uIssuerID=%s saTransferRate=%s")
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRev> uIndex=%d uIssuerID=%s saTransferRate=%s")
|
||||
% uIndex
|
||||
% NewcoinAddress::createHumanAccountID(uCurIssuerID)
|
||||
% saTransferRate.getFullText());
|
||||
@@ -1756,7 +1760,7 @@ TER RippleCalc::calcNodeRev(const unsigned int uIndex, const PathState::pointer&
|
||||
terResult = calcNodeRev(uIndex-1, pspCur, bMultiQuality);
|
||||
}
|
||||
|
||||
Log(lsINFO) << boost::str(boost::format("calcNodeRev< uIndex=%d terResult=%s/%d") % uIndex % transToken(terResult) % terResult);
|
||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRev< uIndex=%d terResult=%s/%d") % uIndex % transToken(terResult) % terResult);
|
||||
|
||||
return terResult;
|
||||
}
|
||||
@@ -1771,7 +1775,7 @@ void RippleCalc::pathNext(const PathState::pointer& pspCur, const int iPaths, co
|
||||
const bool bMultiQuality = iPaths == 1;
|
||||
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
|
||||
|
||||
Log(lsINFO) << "Path In: " << pspCur->getJson();
|
||||
cLog(lsINFO) << "Path In: " << pspCur->getJson();
|
||||
|
||||
assert(pspCur->vpnNodes.size() >= 2);
|
||||
|
||||
@@ -1783,7 +1787,7 @@ void RippleCalc::pathNext(const PathState::pointer& pspCur, const int iPaths, co
|
||||
|
||||
pspCur->terStatus = calcNodeRev(uLast, pspCur, bMultiQuality);
|
||||
|
||||
Log(lsINFO) << "Path after reverse: " << pspCur->getJson();
|
||||
cLog(lsINFO) << "Path after reverse: " << pspCur->getJson();
|
||||
|
||||
if (tesSUCCESS == pspCur->terStatus)
|
||||
{
|
||||
@@ -1797,7 +1801,7 @@ void RippleCalc::pathNext(const PathState::pointer& pspCur, const int iPaths, co
|
||||
? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality.
|
||||
: 0; // Mark path as inactive.
|
||||
|
||||
Log(lsINFO) << "Path after forward: " << pspCur->getJson();
|
||||
cLog(lsINFO) << "Path after forward: " << pspCur->getJson();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1824,7 +1828,7 @@ TER RippleCalc::rippleCalc(
|
||||
|
||||
if (bNoRippleDirect && spsPaths.isEmpty())
|
||||
{
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: No paths and direct ripple not allowed.";
|
||||
cLog(lsINFO) << "doPayment: Invalid transaction: No paths and direct ripple not allowed.";
|
||||
|
||||
return temRIPPLE_EMPTY;
|
||||
}
|
||||
@@ -1836,7 +1840,7 @@ TER RippleCalc::rippleCalc(
|
||||
{
|
||||
// Direct path.
|
||||
// XXX Might also make a stamp bridge by default.
|
||||
Log(lsINFO) << "doPayment: Build direct:";
|
||||
cLog(lsINFO) << "doPayment: Build direct:";
|
||||
|
||||
PathState::pointer pspDirect = PathState::createPathState(
|
||||
vpsPaths.size(),
|
||||
@@ -1863,11 +1867,11 @@ TER RippleCalc::rippleCalc(
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << "doPayment: Paths in set: " << spsPaths.getPathCount();
|
||||
cLog(lsINFO) << "doPayment: Paths in set: " << spsPaths.getPathCount();
|
||||
|
||||
BOOST_FOREACH(const STPath& spPath, spsPaths)
|
||||
{
|
||||
Log(lsINFO) << "doPayment: Build path:";
|
||||
cLog(lsINFO) << "doPayment: Build path:";
|
||||
|
||||
PathState::pointer pspExpanded = PathState::createPathState(
|
||||
vpsPaths.size(),
|
||||
@@ -2099,7 +2103,7 @@ void TransactionEngine::calcOfferBridgeNext(
|
||||
if (sleOffer->isFieldPresent(sfExpiration) && sleOffer->getFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC())
|
||||
{
|
||||
// Offer is expired.
|
||||
Log(lsINFO) << "calcOfferFirst: encountered expired offer";
|
||||
cLog(lsINFO) << "calcOfferFirst: encountered expired offer";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2133,7 +2137,7 @@ void TransactionEngine::calcOfferBridgeNext(
|
||||
if (!saOfferFunds.isPositive())
|
||||
{
|
||||
// Offer is unfunded.
|
||||
Log(lsINFO) << "calcOfferFirst: offer unfunded: delete";
|
||||
cLog(lsINFO) << "calcOfferFirst: offer unfunded: delete";
|
||||
}
|
||||
else if (saOfferFunds >= saOfferPays)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "RippleLines.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Log.h"
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
RippleLines::RippleLines(const uint160& accountID, Ledger::pointer ledger)
|
||||
{
|
||||
@@ -47,7 +51,7 @@ void RippleLines::fillLines(const uint160& accountID, Ledger::pointer ledger)
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsWARNING) << "doRippleLinesGet: Bad index: " << uNode.ToString();
|
||||
cLog(lsWARNING) << "doRippleLinesGet: Bad index: " << uNode.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "SHAMap.h"
|
||||
#include "Application.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
std::size_t hash_value(const SHAMapNode& mn)
|
||||
{
|
||||
std::size_t seed = theApp->getNonceST();
|
||||
@@ -662,7 +664,7 @@ bool SHAMap::updateGiveItem(const SHAMapItem::pointer& item, bool isTransaction,
|
||||
if (!node->setItem(item, !isTransaction ? SHAMapTreeNode::tnACCOUNT_STATE :
|
||||
(hasMeta ? SHAMapTreeNode::tnTRANSACTION_MD : SHAMapTreeNode::tnTRANSACTION_NM)))
|
||||
{
|
||||
Log(lsWARNING) << "SHAMap setItem, no change";
|
||||
cLog(lsWARNING) << "SHAMap setItem, no change";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -695,7 +697,7 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Log(lsWARNING) << "fetchNodeExternal gets an invalid node: " << hash;
|
||||
cLog(lsWARNING) << "fetchNodeExternal gets an invalid node: " << hash;
|
||||
throw SHAMapMissingNode(id, hash);
|
||||
}
|
||||
}
|
||||
@@ -792,7 +794,7 @@ BOOST_AUTO_TEST_SUITE(SHAMap_suite)
|
||||
|
||||
BOOST_AUTO_TEST_CASE( SHAMap_test )
|
||||
{ // h3 and h4 differ only in the leaf, same terminal node (level 19)
|
||||
Log(lsTRACE) << "SHAMap test";
|
||||
cLog(lsTRACE) << "SHAMap test";
|
||||
uint256 h1, h2, h3, h4, h5;
|
||||
h1.SetHex("092891fe4ef6cee585fdc6fda0e09eb4d386363158ec3321b8123e5a772c6ca7");
|
||||
h2.SetHex("436ccbac3347baa1f1e53baeef1f43334da88f1f6d70d963b833afd6dfa289fe");
|
||||
@@ -828,7 +830,7 @@ BOOST_AUTO_TEST_CASE( SHAMap_test )
|
||||
i = sMap.peekNextItem(i->getTag());
|
||||
if (i) BOOST_FAIL("bad traverse");
|
||||
|
||||
Log(lsTRACE) << "SHAMap snap test";
|
||||
cLog(lsTRACE) << "SHAMap snap test";
|
||||
uint256 mapHash = sMap.getHash();
|
||||
SHAMap::pointer map2 = sMap.snapShot(false);
|
||||
if (sMap.getHash() != mapHash) BOOST_FAIL("bad snapshot");
|
||||
|
||||
20
src/SHAMap.h
20
src/SHAMap.h
@@ -23,10 +23,6 @@ class SHAMap;
|
||||
|
||||
class SHAMapNode
|
||||
{ // Identifies a node in a SHA256 hash
|
||||
public:
|
||||
typedef boost::shared_ptr<SHAMapNode> pointer;
|
||||
typedef const boost::shared_ptr<SHAMapNode>& ref;
|
||||
|
||||
private:
|
||||
static uint256 smMasks[65]; // AND with hash to get node id
|
||||
|
||||
@@ -84,7 +80,8 @@ inline std::ostream& operator<<(std::ostream& out, const SHAMapNode& node) { ret
|
||||
class SHAMapItem
|
||||
{ // an item stored in a SHAMap
|
||||
public:
|
||||
typedef boost::shared_ptr<SHAMapItem> pointer;
|
||||
typedef boost::shared_ptr<SHAMapItem> pointer;
|
||||
typedef const boost::shared_ptr<SHAMapItem>& ref;
|
||||
|
||||
private:
|
||||
uint256 mTag;
|
||||
@@ -136,7 +133,8 @@ class SHAMapTreeNode : public SHAMapNode
|
||||
friend class SHAMap;
|
||||
|
||||
public:
|
||||
typedef boost::shared_ptr<SHAMapTreeNode> pointer;
|
||||
typedef boost::shared_ptr<SHAMapTreeNode> pointer;
|
||||
typedef const boost::shared_ptr<SHAMapTreeNode>& ref;
|
||||
|
||||
enum TNType
|
||||
{
|
||||
@@ -163,7 +161,7 @@ private:
|
||||
public:
|
||||
SHAMapTreeNode(uint32 seq, const SHAMapNode& nodeID); // empty node
|
||||
SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq); // copy node from older tree
|
||||
SHAMapTreeNode(const SHAMapNode& nodeID, const SHAMapItem::pointer& item, TNType type, uint32 seq);
|
||||
SHAMapTreeNode(const SHAMapNode& nodeID, SHAMapItem::ref item, TNType type, uint32 seq);
|
||||
|
||||
// raw node functions
|
||||
SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned char>& data, uint32 seq, SHANodeFormat format);
|
||||
@@ -200,7 +198,7 @@ public:
|
||||
|
||||
// item node function
|
||||
bool hasItem() const { return !!mItem; }
|
||||
SHAMapItem::pointer peekItem() { return mItem; }
|
||||
SHAMapItem::ref peekItem() { return mItem; }
|
||||
SHAMapItem::pointer getItem() const;
|
||||
bool setItem(const SHAMapItem::pointer& i, TNType type);
|
||||
const uint256& getTag() const { return mItem->getTag(); }
|
||||
@@ -292,7 +290,7 @@ protected:
|
||||
SHAMapItem::pointer onlyBelow(SHAMapTreeNode*);
|
||||
void eraseChildren(SHAMapTreeNode::pointer);
|
||||
|
||||
bool walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem, bool isFirstMap,
|
||||
bool walkBranch(SHAMapTreeNode* node, SHAMapItem::ref otherMapItem, bool isFirstMap,
|
||||
SHAMapDiff& differences, int& maxCount);
|
||||
|
||||
public:
|
||||
@@ -321,8 +319,8 @@ public:
|
||||
uint256 getHash() { return root->getNodeHash(); }
|
||||
|
||||
// save a copy if you have a temporary anyway
|
||||
bool updateGiveItem(const SHAMapItem::pointer&, bool isTransaction, bool hasMeta);
|
||||
bool addGiveItem(const SHAMapItem::pointer&, bool isTransaction, bool hasMeta);
|
||||
bool updateGiveItem(SHAMapItem::ref, bool isTransaction, bool hasMeta);
|
||||
bool addGiveItem(SHAMapItem::ref, bool isTransaction, bool hasMeta);
|
||||
|
||||
// save a copy if you only need a temporary
|
||||
SHAMapItem::pointer peekItem(const uint256& id);
|
||||
|
||||
@@ -20,13 +20,15 @@ class SHAMapDiffNode
|
||||
mNodeID(id), mOurHash(ourHash), mOtherHash(otherHash) { ; }
|
||||
};
|
||||
|
||||
bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem, bool isFirstMap,
|
||||
bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::ref otherMapItem, bool isFirstMap,
|
||||
SHAMapDiff& differences, int& maxCount)
|
||||
{
|
||||
// Walk a branch of a SHAMap that's matched by an empty branch or single item in the other map
|
||||
std::stack<SHAMapTreeNode*> nodeStack;
|
||||
nodeStack.push(node);
|
||||
|
||||
|
||||
bool emptyBranch = !otherMapItem;
|
||||
|
||||
while (!nodeStack.empty())
|
||||
{
|
||||
SHAMapTreeNode* node = nodeStack.top();
|
||||
@@ -41,7 +43,7 @@ bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem,
|
||||
{ // This is a leaf node, process its item
|
||||
SHAMapItem::pointer item = node->getItem();
|
||||
|
||||
if (otherMapItem && (otherMapItem->getTag() < item->getTag()))
|
||||
if (!emptyBranch && (otherMapItem->getTag() < item->getTag()))
|
||||
{ // this item comes after the item from the other map, so add the other item
|
||||
if (isFirstMap) // this is first map, so other item is from second
|
||||
differences.insert(std::make_pair(otherMapItem->getTag(),
|
||||
@@ -49,11 +51,12 @@ bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem,
|
||||
else
|
||||
differences.insert(std::make_pair(otherMapItem->getTag(),
|
||||
std::make_pair(otherMapItem, SHAMapItem::pointer())));
|
||||
if (--maxCount <= 0) return false;
|
||||
otherMapItem = SHAMapItem::pointer();
|
||||
if (--maxCount <= 0)
|
||||
return false;
|
||||
emptyBranch = true;
|
||||
}
|
||||
|
||||
if ((!otherMapItem) || (item->getTag() < otherMapItem->getTag()))
|
||||
if (emptyBranch || (item->getTag() < otherMapItem->getTag()))
|
||||
{ // unmatched
|
||||
if (isFirstMap)
|
||||
differences.insert(std::make_pair(item->getTag(), std::make_pair(item, SHAMapItem::pointer())));
|
||||
@@ -77,7 +80,7 @@ bool SHAMap::walkBranch(SHAMapTreeNode* node, SHAMapItem::pointer otherMapItem,
|
||||
}
|
||||
}
|
||||
|
||||
if (otherMapItem)
|
||||
if (!emptyBranch)
|
||||
{ // otherMapItem was unmatched, must add
|
||||
if (isFirstMap) // this is first map, so other item is from second
|
||||
differences.insert(std::make_pair(otherMapItem->getTag(),
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "Log.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
|
||||
SHAMapSyncFilter* filter)
|
||||
{
|
||||
@@ -26,7 +28,7 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
|
||||
if (!root->isInner())
|
||||
{
|
||||
Log(lsWARNING) << "synching empty tree";
|
||||
cLog(lsWARNING) << "synching empty tree";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -61,12 +63,12 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
d = boost::make_shared<SHAMapTreeNode>(childID, nodeData, mSeq, snfPREFIX);
|
||||
if (childHash != d->getNodeHash())
|
||||
{
|
||||
Log(lsERROR) << "Wrong hash from cached object";
|
||||
cLog(lsERROR) << "Wrong hash from cached object";
|
||||
d = SHAMapTreeNode::pointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsTRACE) << "Got sync node from cache: " << *d;
|
||||
cLog(lsTRACE) << "Got sync node from cache: " << *d;
|
||||
mTNByID[*d] = d;
|
||||
}
|
||||
}
|
||||
@@ -136,7 +138,7 @@ bool SHAMap::addRootNode(const std::vector<unsigned char>& rootNode, SHANodeForm
|
||||
// we already have a root node
|
||||
if (root->getNodeHash().isNonZero())
|
||||
{
|
||||
Log(lsTRACE) << "got root node, already have one";
|
||||
cLog(lsTRACE) << "got root node, already have one";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -168,7 +170,7 @@ bool SHAMap::addRootNode(const uint256& hash, const std::vector<unsigned char>&
|
||||
// we already have a root node
|
||||
if (root->getNodeHash().isNonZero())
|
||||
{
|
||||
Log(lsTRACE) << "got root node, already have one";
|
||||
cLog(lsTRACE) << "got root node, already have one";
|
||||
assert(root->getNodeHash() == hash);
|
||||
return true;
|
||||
}
|
||||
@@ -216,15 +218,15 @@ bool SHAMap::addKnownNode(const SHAMapNode& node, const std::vector<unsigned cha
|
||||
|
||||
if (iNode->isLeaf() || (iNode->getDepth() == node.getDepth()))
|
||||
{
|
||||
Log(lsTRACE) << "got inner node, already had it (late)";
|
||||
cLog(lsTRACE) << "got inner node, already had it (late)";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (iNode->getDepth() != (node.getDepth() - 1))
|
||||
{ // Either this node is broken or we didn't request it (yet)
|
||||
Log(lsINFO) << "unable to hook node " << node;
|
||||
Log(lsINFO) << " stuck at " << *iNode;
|
||||
Log(lsINFO) << "got depth=" << node.getDepth() << ", walked to= " << iNode->getDepth();
|
||||
cLog(lsINFO) << "unable to hook node " << node;
|
||||
cLog(lsINFO) << " stuck at " << *iNode;
|
||||
cLog(lsINFO) << "got depth=" << node.getDepth() << ", walked to= " << iNode->getDepth();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -295,16 +297,16 @@ bool SHAMap::deepCompare(SHAMap& other)
|
||||
|
||||
if (!otherNode)
|
||||
{
|
||||
Log(lsINFO) << "unable to fetch node";
|
||||
cLog(lsINFO) << "unable to fetch node";
|
||||
return false;
|
||||
}
|
||||
else if (otherNode->getNodeHash() != node->getNodeHash())
|
||||
{
|
||||
Log(lsWARNING) << "node hash mismatch";
|
||||
cLog(lsWARNING) << "node hash mismatch";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log(lsTRACE) << "Comparing inner nodes " << *node;
|
||||
// cLog(lsTRACE) << "Comparing inner nodes " << *node;
|
||||
|
||||
if (node->getNodeHash() != otherNode->getNodeHash())
|
||||
return false;
|
||||
@@ -329,7 +331,7 @@ bool SHAMap::deepCompare(SHAMap& other)
|
||||
SHAMapTreeNode::pointer next = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||
if (!next)
|
||||
{
|
||||
Log(lsWARNING) << "unable to fetch inner node";
|
||||
cLog(lsWARNING) << "unable to fetch inner node";
|
||||
return false;
|
||||
}
|
||||
stack.push(next);
|
||||
@@ -365,7 +367,7 @@ static bool confuseMap(SHAMap &map, int count)
|
||||
items.push_back(item->getTag());
|
||||
if (!map.addItem(*item, false, false))
|
||||
{
|
||||
Log(lsFATAL) << "Unable to add item to map";
|
||||
cLog(lsFATAL) << "Unable to add item to map";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -374,14 +376,14 @@ static bool confuseMap(SHAMap &map, int count)
|
||||
{
|
||||
if (!map.delItem(*it))
|
||||
{
|
||||
Log(lsFATAL) << "Unable to remove item from map";
|
||||
cLog(lsFATAL) << "Unable to remove item from map";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeHash != map.getHash())
|
||||
{
|
||||
Log(lsFATAL) << "Hashes do not match";
|
||||
cLog(lsFATAL) << "Hashes do not match";
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -412,26 +414,26 @@ BOOST_AUTO_TEST_SUITE( SHAMapSync )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
{
|
||||
Log(lsTRACE) << "being sync test";
|
||||
cLog(lsTRACE) << "being sync test";
|
||||
unsigned int seed;
|
||||
RAND_pseudo_bytes(reinterpret_cast<unsigned char *>(&seed), sizeof(seed));
|
||||
srand(seed);
|
||||
|
||||
Log(lsTRACE) << "Constructing maps";
|
||||
cLog(lsTRACE) << "Constructing maps";
|
||||
SHAMap source, destination;
|
||||
|
||||
// add random data to the source map
|
||||
Log(lsTRACE) << "Adding random data";
|
||||
cLog(lsTRACE) << "Adding random data";
|
||||
int items = 10000;
|
||||
for (int i = 0; i < items; ++i)
|
||||
source.addItem(*makeRandomAS(), false, false);
|
||||
|
||||
Log(lsTRACE) << "Adding items, then removing them";
|
||||
cLog(lsTRACE) << "Adding items, then removing them";
|
||||
if (!confuseMap(source, 500)) BOOST_FAIL("ConfuseMap");
|
||||
|
||||
source.setImmutable();
|
||||
|
||||
Log(lsTRACE) << "SOURCE COMPLETE, SYNCHING";
|
||||
cLog(lsTRACE) << "SOURCE COMPLETE, SYNCHING";
|
||||
|
||||
std::vector<SHAMapNode> nodeIDs, gotNodeIDs;
|
||||
std::list< std::vector<unsigned char> > gotNodes;
|
||||
@@ -447,23 +449,23 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
|
||||
if (!source.getNodeFat(SHAMapNode(), nodeIDs, gotNodes, (rand() % 2) == 0, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat(root) fails";
|
||||
cLog(lsFATAL) << "GetNodeFat(root) fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
}
|
||||
if (gotNodes.size() < 1)
|
||||
{
|
||||
Log(lsFATAL) << "Didn't get root node " << gotNodes.size();
|
||||
cLog(lsFATAL) << "Didn't get root node " << gotNodes.size();
|
||||
BOOST_FAIL("NodeSize");
|
||||
}
|
||||
if (!destination.addRootNode(*gotNodes.begin(), snfWIRE))
|
||||
{
|
||||
Log(lsFATAL) << "AddRootNode fails";
|
||||
cLog(lsFATAL) << "AddRootNode fails";
|
||||
BOOST_FAIL("AddRootNode");
|
||||
}
|
||||
nodeIDs.clear();
|
||||
gotNodes.clear();
|
||||
|
||||
Log(lsINFO) << "ROOT COMPLETE, INNER SYNCHING";
|
||||
cLog(lsINFO) << "ROOT COMPLETE, INNER SYNCHING";
|
||||
#ifdef SMS_DEBUG
|
||||
int bytes = 0;
|
||||
#endif
|
||||
@@ -477,14 +479,14 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
destination.getMissingNodes(nodeIDs, hashes, 2048, NULL);
|
||||
if (nodeIDs.empty()) break;
|
||||
|
||||
Log(lsINFO) << nodeIDs.size() << " needed nodes";
|
||||
cLog(lsINFO) << nodeIDs.size() << " needed nodes";
|
||||
|
||||
// get as many nodes as possible based on this information
|
||||
for (nodeIDIterator = nodeIDs.begin(); nodeIDIterator != nodeIDs.end(); ++nodeIDIterator)
|
||||
{
|
||||
if (!source.getNodeFat(*nodeIDIterator, gotNodeIDs, gotNodes, (rand() % 2) == 0, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat fails";
|
||||
cLog(lsFATAL) << "GetNodeFat fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
}
|
||||
}
|
||||
@@ -494,11 +496,11 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
|
||||
if (gotNodeIDs.empty())
|
||||
{
|
||||
Log(lsFATAL) << "No nodes gotten";
|
||||
cLog(lsFATAL) << "No nodes gotten";
|
||||
BOOST_FAIL("Got Node ID");
|
||||
}
|
||||
|
||||
Log(lsTRACE) << gotNodeIDs.size() << " found nodes";
|
||||
cLog(lsTRACE) << gotNodeIDs.size() << " found nodes";
|
||||
for (nodeIDIterator = gotNodeIDs.begin(), rawNodeIterator = gotNodes.begin();
|
||||
nodeIDIterator != gotNodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
|
||||
{
|
||||
@@ -508,7 +510,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
#endif
|
||||
if (!destination.addKnownNode(*nodeIDIterator, *rawNodeIterator, NULL))
|
||||
{
|
||||
Log(lsTRACE) << "AddKnownNode fails";
|
||||
cLog(lsTRACE) << "AddKnownNode fails";
|
||||
BOOST_FAIL("AddKnownNode");
|
||||
}
|
||||
}
|
||||
@@ -520,18 +522,18 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
destination.clearSynching();
|
||||
|
||||
#ifdef SMS_DEBUG
|
||||
Log(lsINFO) << "SYNCHING COMPLETE " << items << " items, " << nodes << " nodes, " <<
|
||||
cLog(lsINFO) << "SYNCHING COMPLETE " << items << " items, " << nodes << " nodes, " <<
|
||||
bytes / 1024 << " KB";
|
||||
#endif
|
||||
|
||||
if (!source.deepCompare(destination))
|
||||
{
|
||||
Log(lsFATAL) << "DeepCompare fails";
|
||||
cLog(lsFATAL) << "DeepCompare fails";
|
||||
BOOST_FAIL("Deep Compare");
|
||||
}
|
||||
|
||||
#ifdef SMS_DEBUG
|
||||
Log(lsINFO) << "SHAMapSync test passed: " << items << " items, " <<
|
||||
cLog(lsINFO) << "SHAMapSync test passed: " << items << " items, " <<
|
||||
passes << " passes, " << nodes << " nodes";
|
||||
#endif
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
FIELD(TransactionType, UINT16, 2)
|
||||
|
||||
// 32-bit integers (common)
|
||||
FIELD(ObjectType, UINT32, 1)
|
||||
FIELD(Flags, UINT32, 2)
|
||||
FIELD(SourceTag, UINT32, 3)
|
||||
FIELD(Sequence, UINT32, 4)
|
||||
@@ -91,7 +90,7 @@
|
||||
FIELD(Fee, AMOUNT, 8)
|
||||
FIELD(SendMax, AMOUNT, 9)
|
||||
|
||||
// current amount (uncommon)
|
||||
// currency amount (uncommon)
|
||||
FIELD(MinimumOffer, AMOUNT, 16)
|
||||
FIELD(RippleEscrow, AMOUNT, 17)
|
||||
|
||||
@@ -113,8 +112,6 @@
|
||||
FIELD(Owner, ACCOUNT, 2)
|
||||
FIELD(Destination, ACCOUNT, 3)
|
||||
FIELD(Issuer, ACCOUNT, 4)
|
||||
FIELD(HighID, ACCOUNT, 5)
|
||||
FIELD(LowID, ACCOUNT, 6)
|
||||
FIELD(Target, ACCOUNT, 7)
|
||||
FIELD(AuthorizedKey, ACCOUNT, 8)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "Log.h"
|
||||
#include "LedgerFormats.h"
|
||||
#include "TransactionFormats.h"
|
||||
#include "SerializedTransaction.h"
|
||||
|
||||
std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, SField::ref name)
|
||||
{
|
||||
@@ -153,7 +154,7 @@ bool STObject::setType(const std::vector<SOElement::ptr> &type)
|
||||
{
|
||||
if (elem->flags != SOE_OPTIONAL)
|
||||
{
|
||||
Log(lsTRACE) << "setType !valid missing";
|
||||
Log(lsWARNING) << "setType !valid missing " << elem->e_field.fieldName;
|
||||
valid = false;
|
||||
}
|
||||
newData.push_back(makeNonPresentObject(elem->e_field));
|
||||
@@ -163,8 +164,14 @@ bool STObject::setType(const std::vector<SOElement::ptr> &type)
|
||||
}
|
||||
if (mData.size() != 0)
|
||||
{
|
||||
Log(lsTRACE) << "setType !valid leftover";
|
||||
valid = false;
|
||||
BOOST_FOREACH(const SerializedType& t, mData)
|
||||
{
|
||||
if (!t.getFName().isDiscardable())
|
||||
{
|
||||
Log(lsWARNING) << "setType !valid leftover: " << t.getFName().getName();
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mData.swap(newData);
|
||||
return valid;
|
||||
@@ -367,11 +374,15 @@ const SerializedType* STObject::peekAtPField(SField::ref field) const
|
||||
return peekAtPIndex(index);
|
||||
}
|
||||
|
||||
SerializedType* STObject::getPField(SField::ref field)
|
||||
SerializedType* STObject::getPField(SField::ref field, bool createOkay)
|
||||
{
|
||||
int index = getFieldIndex(field);
|
||||
if (index == -1)
|
||||
{
|
||||
if (createOkay && isFree())
|
||||
return getPIndex(giveObject(makeDefaultObject(field)));
|
||||
return NULL;
|
||||
}
|
||||
return getPIndex(index);
|
||||
}
|
||||
|
||||
@@ -385,7 +396,7 @@ bool STObject::isFieldPresent(SField::ref field) const
|
||||
|
||||
bool STObject::setFlag(uint32 f)
|
||||
{
|
||||
STUInt32* t = dynamic_cast<STUInt32*>(getPField(sfFlags));
|
||||
STUInt32* t = dynamic_cast<STUInt32*>(getPField(sfFlags, true));
|
||||
if (!t)
|
||||
return false;
|
||||
t->setValue(t->getValue() | f);
|
||||
@@ -413,7 +424,11 @@ SerializedType* STObject::makeFieldPresent(SField::ref field)
|
||||
{
|
||||
int index = getFieldIndex(field);
|
||||
if (index == -1)
|
||||
throw std::runtime_error("Field not found");
|
||||
{
|
||||
if (!isFree())
|
||||
throw std::runtime_error("Field not found");
|
||||
return getPIndex(giveObject(makeNonPresentObject(field)));
|
||||
}
|
||||
|
||||
SerializedType* f = getPIndex(index);
|
||||
if (f->getSType() != STI_NOTPRESENT)
|
||||
@@ -619,7 +634,7 @@ STVector256 STObject::getFieldV256(SField::ref field) const
|
||||
|
||||
void STObject::setFieldU8(SField::ref field, unsigned char v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STUInt8* cf = dynamic_cast<STUInt8*>(rf);
|
||||
@@ -629,7 +644,7 @@ void STObject::setFieldU8(SField::ref field, unsigned char v)
|
||||
|
||||
void STObject::setFieldU16(SField::ref field, uint16 v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STUInt16* cf = dynamic_cast<STUInt16*>(rf);
|
||||
@@ -639,7 +654,7 @@ void STObject::setFieldU16(SField::ref field, uint16 v)
|
||||
|
||||
void STObject::setFieldU32(SField::ref field, uint32 v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STUInt32* cf = dynamic_cast<STUInt32*>(rf);
|
||||
@@ -649,7 +664,7 @@ void STObject::setFieldU32(SField::ref field, uint32 v)
|
||||
|
||||
void STObject::setFieldU64(SField::ref field, uint64 v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STUInt64* cf = dynamic_cast<STUInt64*>(rf);
|
||||
@@ -659,7 +674,7 @@ void STObject::setFieldU64(SField::ref field, uint64 v)
|
||||
|
||||
void STObject::setFieldH128(SField::ref field, const uint128& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STHash128* cf = dynamic_cast<STHash128*>(rf);
|
||||
@@ -669,7 +684,7 @@ void STObject::setFieldH128(SField::ref field, const uint128& v)
|
||||
|
||||
void STObject::setFieldH160(SField::ref field, const uint160& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STHash160* cf = dynamic_cast<STHash160*>(rf);
|
||||
@@ -679,7 +694,7 @@ void STObject::setFieldH160(SField::ref field, const uint160& v)
|
||||
|
||||
void STObject::setFieldH256(SField::ref field, const uint256& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STHash256* cf = dynamic_cast<STHash256*>(rf);
|
||||
@@ -689,7 +704,7 @@ void STObject::setFieldH256(SField::ref field, const uint256& v)
|
||||
|
||||
void STObject::setFieldV256(SField::ref field, const STVector256& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STVector256* cf = dynamic_cast<STVector256*>(rf);
|
||||
@@ -699,7 +714,7 @@ void STObject::setFieldV256(SField::ref field, const STVector256& v)
|
||||
|
||||
void STObject::setFieldAccount(SField::ref field, const uint160& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STAccount* cf = dynamic_cast<STAccount*>(rf);
|
||||
@@ -709,7 +724,7 @@ void STObject::setFieldAccount(SField::ref field, const uint160& v)
|
||||
|
||||
void STObject::setFieldVL(SField::ref field, const std::vector<unsigned char>& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STVariableLength* cf = dynamic_cast<STVariableLength*>(rf);
|
||||
@@ -719,7 +734,7 @@ void STObject::setFieldVL(SField::ref field, const std::vector<unsigned char>& v
|
||||
|
||||
void STObject::setFieldAmount(SField::ref field, const STAmount &v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STAmount* cf = dynamic_cast<STAmount*>(rf);
|
||||
@@ -729,7 +744,7 @@ void STObject::setFieldAmount(SField::ref field, const STAmount &v)
|
||||
|
||||
void STObject::setFieldPathSet(SField::ref field, const STPathSet &v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
SerializedType* rf = getPField(field, true);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STPathSet* cf = dynamic_cast<STPathSet*>(rf);
|
||||
@@ -939,7 +954,7 @@ std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::r
|
||||
|
||||
case STI_UINT64:
|
||||
if (value.isString())
|
||||
data.push_back(new STUInt64(field, lexical_cast_st<uint64>(value.asString())));
|
||||
data.push_back(new STUInt64(field, uintFromHex(value.asString())));
|
||||
else if (value.isInt())
|
||||
data.push_back(new STUInt64(field,
|
||||
range_check_cast<uint64>(value.asInt(), 0, 18446744073709551615ull)));
|
||||
@@ -1116,6 +1131,7 @@ std::auto_ptr<STObject> STObject::parseJson(const Json::Value& object, SField::r
|
||||
throw std::runtime_error("Invalid field type");
|
||||
}
|
||||
}
|
||||
|
||||
return std::auto_ptr<STObject>(new STObject(*name, data));
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
bool setType(const std::vector<SOElement::ptr>& type);
|
||||
bool isValidForType();
|
||||
bool isFieldAllowed(SField::ref);
|
||||
bool isFree() const { return mType.empty(); }
|
||||
|
||||
void set(const std::vector<SOElement::ptr>&);
|
||||
bool set(SerializerIterator& u, int depth = 0);
|
||||
@@ -95,7 +96,7 @@ public:
|
||||
const SerializedType& peekAtField(SField::ref field) const;
|
||||
SerializedType& getField(SField::ref field);
|
||||
const SerializedType* peekAtPField(SField::ref field) const;
|
||||
SerializedType* getPField(SField::ref field);
|
||||
SerializedType* getPField(SField::ref field, bool createOkay = false);
|
||||
|
||||
// these throw if the field type doesn't match, or return default values if the
|
||||
// field is optional but not present
|
||||
|
||||
@@ -17,6 +17,19 @@ SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sf
|
||||
setFieldU16(sfTransactionType, mFormat->t_type);
|
||||
}
|
||||
|
||||
SerializedTransaction::SerializedTransaction(const STObject& object) : STObject(object)
|
||||
{
|
||||
mType = static_cast<TransactionType>(getFieldU16(sfTransactionType));
|
||||
mFormat = TransactionFormat::getTxnFormat(mType);
|
||||
if (!mFormat)
|
||||
throw std::runtime_error("invalid transaction type");
|
||||
if (!setType(mFormat->elements))
|
||||
{
|
||||
assert(false);
|
||||
throw std::runtime_error("transaction not valid");
|
||||
}
|
||||
}
|
||||
|
||||
SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject(sfTransaction)
|
||||
{
|
||||
int length = sit.getBytesLeft();
|
||||
@@ -209,9 +222,9 @@ BOOST_AUTO_TEST_CASE( STrans_test )
|
||||
Log(lsFATAL) << copy.getJson(0);
|
||||
BOOST_FAIL("Transaction fails serialize/deserialize test");
|
||||
}
|
||||
Log(lsINFO) << "ORIG: " << j.getJson(0);
|
||||
std::auto_ptr<STObject> new_obj = STObject::parseJson(j.getJson(0), sfGeneric);
|
||||
if (new_obj.get() == NULL) BOOST_FAIL("Unable to build object from json");
|
||||
Log(lsINFO) << "ORIG: " << j.getJson(0);
|
||||
Log(lsINFO) << "BUILT " << new_obj->getJson(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ protected:
|
||||
public:
|
||||
SerializedTransaction(SerializerIterator& sit);
|
||||
SerializedTransaction(TransactionType type);
|
||||
SerializedTransaction(const STObject &object);
|
||||
|
||||
// STObject functions
|
||||
SerializedTypeID getSType() const { return STI_TRANSACTION; }
|
||||
|
||||
@@ -64,6 +64,11 @@ std::string STUInt8::getText() const
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
}
|
||||
|
||||
Json::Value STUInt8::getJson(int) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool STUInt8::isEquivalent(const SerializedType& t) const
|
||||
{
|
||||
const STUInt8* v = dynamic_cast<const STUInt8*>(&t);
|
||||
@@ -92,6 +97,23 @@ std::string STUInt16::getText() const
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
}
|
||||
|
||||
Json::Value STUInt16::getJson(int) const
|
||||
{
|
||||
if (getFName() == sfLedgerEntryType)
|
||||
{
|
||||
LedgerEntryFormat *f = LedgerEntryFormat::getLgrFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
if (getFName() == sfTransactionType)
|
||||
{
|
||||
TransactionFormat *f = TransactionFormat::getTxnFormat(value);
|
||||
if (f != NULL)
|
||||
return f->t_name;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool STUInt16::isEquivalent(const SerializedType& t) const
|
||||
{
|
||||
const STUInt16* v = dynamic_cast<const STUInt16*>(&t);
|
||||
@@ -108,6 +130,11 @@ std::string STUInt32::getText() const
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
}
|
||||
|
||||
Json::Value STUInt32::getJson(int) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool STUInt32::isEquivalent(const SerializedType& t) const
|
||||
{
|
||||
const STUInt32* v = dynamic_cast<const STUInt32*>(&t);
|
||||
@@ -124,6 +151,11 @@ std::string STUInt64::getText() const
|
||||
return boost::lexical_cast<std::string>(value);
|
||||
}
|
||||
|
||||
Json::Value STUInt64::getJson(int) const
|
||||
{
|
||||
return strHex(value);
|
||||
}
|
||||
|
||||
bool STUInt64::isEquivalent(const SerializedType& t) const
|
||||
{
|
||||
const STUInt64* v = dynamic_cast<const STUInt64*>(&t);
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
|
||||
SerializedTypeID getSType() const { return STI_UINT8; }
|
||||
std::string getText() const;
|
||||
Json::Value getJson(int) const;
|
||||
void add(Serializer& s) const { s.add8(value); }
|
||||
|
||||
unsigned char getValue() const { return value; }
|
||||
@@ -123,6 +124,7 @@ public:
|
||||
|
||||
SerializedTypeID getSType() const { return STI_UINT16; }
|
||||
std::string getText() const;
|
||||
Json::Value getJson(int) const;
|
||||
void add(Serializer& s) const { s.add16(value); }
|
||||
|
||||
uint16 getValue() const { return value; }
|
||||
@@ -149,6 +151,7 @@ public:
|
||||
|
||||
SerializedTypeID getSType() const { return STI_UINT32; }
|
||||
std::string getText() const;
|
||||
Json::Value getJson(int) const;
|
||||
void add(Serializer& s) const { s.add32(value); }
|
||||
|
||||
uint32 getValue() const { return value; }
|
||||
@@ -175,6 +178,7 @@ public:
|
||||
|
||||
SerializedTypeID getSType() const { return STI_UINT64; }
|
||||
std::string getText() const;
|
||||
Json::Value getJson(int) const;
|
||||
void add(Serializer& s) const { s.add64(value); }
|
||||
|
||||
uint64 getValue() const { return value; }
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "TransactionFormats.h"
|
||||
#include "utils.h"
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
void TransactionEngine::txnWrite()
|
||||
{
|
||||
// Write back the account states
|
||||
@@ -32,7 +34,7 @@ void TransactionEngine::txnWrite()
|
||||
|
||||
case taaCREATE:
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: taaCREATE: " << sleEntry->getText();
|
||||
cLog(lsINFO) << "applyTransaction: taaCREATE: " << sleEntry->getText();
|
||||
|
||||
if (mLedger->writeBack(lepCREATE, sleEntry) & lepERROR)
|
||||
assert(false);
|
||||
@@ -41,7 +43,7 @@ void TransactionEngine::txnWrite()
|
||||
|
||||
case taaMODIFY:
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: taaMODIFY: " << sleEntry->getText();
|
||||
cLog(lsINFO) << "applyTransaction: taaMODIFY: " << sleEntry->getText();
|
||||
|
||||
if (mLedger->writeBack(lepNONE, sleEntry) & lepERROR)
|
||||
assert(false);
|
||||
@@ -50,7 +52,7 @@ void TransactionEngine::txnWrite()
|
||||
|
||||
case taaDELETE:
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: taaDELETE: " << sleEntry->getText();
|
||||
cLog(lsINFO) << "applyTransaction: taaDELETE: " << sleEntry->getText();
|
||||
|
||||
if (!mLedger->peekAccountStateMap()->delItem(it->first))
|
||||
assert(false);
|
||||
@@ -62,7 +64,7 @@ void TransactionEngine::txnWrite()
|
||||
|
||||
TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params)
|
||||
{
|
||||
Log(lsTRACE) << "applyTransaction>";
|
||||
cLog(lsTRACE) << "applyTransaction>";
|
||||
assert(mLedger);
|
||||
mNodes.init(mLedger, txn.getTransactionID(), mLedger->getLedgerSeq());
|
||||
|
||||
@@ -75,10 +77,10 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
SerializedTransaction s2(sit);
|
||||
if (!s2.isEquivalent(txn))
|
||||
{
|
||||
Log(lsFATAL) << "Transaction serdes mismatch";
|
||||
cLog(lsFATAL) << "Transaction serdes mismatch";
|
||||
Json::StyledStreamWriter ssw;
|
||||
ssw.write(Log(lsINFO).ref(), txn.getJson(0));
|
||||
ssw.write(Log(lsFATAL).ref(), s2.getJson(0));
|
||||
cLog(lsINFO) << txn.getJson(0);
|
||||
cLog(lsFATAL) << s2.getJson(0);
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +90,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
uint256 txID = txn.getTransactionID();
|
||||
if (!txID)
|
||||
{
|
||||
Log(lsWARNING) << "applyTransaction: invalid transaction id";
|
||||
cLog(lsWARNING) << "applyTransaction: invalid transaction id";
|
||||
|
||||
terResult = temINVALID;
|
||||
}
|
||||
@@ -110,7 +112,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
// Consistency: really signed.
|
||||
if ((tesSUCCESS == terResult) && !isSetBit(params, tapNO_CHECK_SIGN) && !txn.checkSign(naSigningPubKey))
|
||||
{
|
||||
Log(lsWARNING) << "applyTransaction: Invalid transaction: bad signature";
|
||||
cLog(lsWARNING) << "applyTransaction: Invalid transaction: bad signature";
|
||||
|
||||
terResult = temINVALID;
|
||||
}
|
||||
@@ -153,12 +155,12 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
break;
|
||||
|
||||
case ttINVALID:
|
||||
Log(lsWARNING) << "applyTransaction: Invalid transaction: ttINVALID transaction type";
|
||||
cLog(lsWARNING) << "applyTransaction: Invalid transaction: ttINVALID transaction type";
|
||||
terResult = temINVALID;
|
||||
break;
|
||||
|
||||
default:
|
||||
Log(lsWARNING) << "applyTransaction: Invalid transaction: unknown transaction type";
|
||||
cLog(lsWARNING) << "applyTransaction: Invalid transaction: unknown transaction type";
|
||||
terResult = temUNKNOWN;
|
||||
break;
|
||||
}
|
||||
@@ -173,7 +175,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
// Only check fee is sufficient when the ledger is open.
|
||||
if (isSetBit(params, tapOPEN_LEDGER) && saPaid < saCost)
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: insufficient fee";
|
||||
cLog(lsINFO) << "applyTransaction: insufficient fee";
|
||||
|
||||
terResult = telINSUF_FEE_P;
|
||||
}
|
||||
@@ -183,7 +185,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
if (saPaid)
|
||||
{
|
||||
// Transaction is malformed.
|
||||
Log(lsWARNING) << "applyTransaction: fee not allowed";
|
||||
cLog(lsWARNING) << "applyTransaction: fee not allowed";
|
||||
|
||||
terResult = temINSUF_FEE_P;
|
||||
}
|
||||
@@ -194,7 +196,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
mTxnAccountID = txn.getSourceAccount().getAccountID();
|
||||
if (tesSUCCESS == terResult && !mTxnAccountID)
|
||||
{
|
||||
Log(lsWARNING) << "applyTransaction: bad source id";
|
||||
cLog(lsWARNING) << "applyTransaction: bad source id";
|
||||
|
||||
terResult = temINVALID;
|
||||
}
|
||||
@@ -215,7 +217,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
|
||||
if (!mTxnAccount)
|
||||
{
|
||||
Log(lsTRACE) << boost::str(boost::format("applyTransaction: Delay transaction: source account does not exist: %s") %
|
||||
cLog(lsTRACE) << boost::str(boost::format("applyTransaction: Delay transaction: source account does not exist: %s") %
|
||||
txn.getSourceAccount().humanAccountID());
|
||||
|
||||
terResult = terNO_ACCOUNT;
|
||||
@@ -234,7 +236,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
case ttCLAIM:
|
||||
if (bHaveAuthKey)
|
||||
{
|
||||
Log(lsWARNING) << "applyTransaction: Account already claimed.";
|
||||
cLog(lsWARNING) << "applyTransaction: Account already claimed.";
|
||||
|
||||
terResult = tefCLAIMED;
|
||||
}
|
||||
@@ -257,8 +259,8 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
if (naSigningPubKey.getAccountID() != mTxnAccountID)
|
||||
{
|
||||
// Signing Pub Key must be for Source Account ID.
|
||||
Log(lsWARNING) << "sourceAccountID: " << naSigningPubKey.humanAccountID();
|
||||
Log(lsWARNING) << "txn accountID: " << txn.getSourceAccount().humanAccountID();
|
||||
cLog(lsWARNING) << "sourceAccountID: " << naSigningPubKey.humanAccountID();
|
||||
cLog(lsWARNING) << "txn accountID: " << txn.getSourceAccount().humanAccountID();
|
||||
|
||||
terResult = tefBAD_CLAIM_ID;
|
||||
}
|
||||
@@ -270,8 +272,8 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
if (naSigningPubKey.getAccountID() != mTxnAccountID)
|
||||
{
|
||||
// Signing Pub Key must be for Source Account ID.
|
||||
Log(lsWARNING) << "sourceAccountID: " << naSigningPubKey.humanAccountID();
|
||||
Log(lsWARNING) << "txn accountID: " << txn.getSourceAccount().humanAccountID();
|
||||
cLog(lsWARNING) << "sourceAccountID: " << naSigningPubKey.humanAccountID();
|
||||
cLog(lsWARNING) << "txn accountID: " << txn.getSourceAccount().humanAccountID();
|
||||
|
||||
terResult = temBAD_SET_ID;
|
||||
}
|
||||
@@ -291,13 +293,13 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
}
|
||||
else if (bHaveAuthKey)
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: Delay: Not authorized to use account.";
|
||||
cLog(lsINFO) << "applyTransaction: Delay: Not authorized to use account.";
|
||||
|
||||
terResult = tefBAD_AUTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: Invalid: Not authorized to use account.";
|
||||
cLog(lsINFO) << "applyTransaction: Invalid: Not authorized to use account.";
|
||||
|
||||
terResult = temBAD_AUTH_MASTER;
|
||||
}
|
||||
@@ -313,7 +315,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
}
|
||||
else if (saSrcBalance < saPaid)
|
||||
{
|
||||
Log(lsINFO)
|
||||
cLog(lsINFO)
|
||||
<< boost::str(boost::format("applyTransaction: Delay: insufficient balance: balance=%s paid=%s")
|
||||
% saSrcBalance.getText()
|
||||
% saPaid.getText());
|
||||
@@ -334,13 +336,13 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
{
|
||||
uint32 a_seq = mTxnAccount->getFieldU32(sfSequence);
|
||||
|
||||
Log(lsTRACE) << "Aseq=" << a_seq << ", Tseq=" << t_seq;
|
||||
cLog(lsTRACE) << "Aseq=" << a_seq << ", Tseq=" << t_seq;
|
||||
|
||||
if (t_seq != a_seq)
|
||||
{
|
||||
if (a_seq < t_seq)
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: future sequence number";
|
||||
cLog(lsINFO) << "applyTransaction: future sequence number";
|
||||
|
||||
terResult = terPRE_SEQ;
|
||||
}
|
||||
@@ -348,7 +350,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
terResult = tefALREADY;
|
||||
else
|
||||
{
|
||||
Log(lsWARNING) << "applyTransaction: past sequence number";
|
||||
cLog(lsWARNING) << "applyTransaction: past sequence number";
|
||||
|
||||
terResult = tefPAST_SEQ;
|
||||
}
|
||||
@@ -360,11 +362,11 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: Zero cost transaction";
|
||||
cLog(lsINFO) << "applyTransaction: Zero cost transaction";
|
||||
|
||||
if (t_seq)
|
||||
{
|
||||
Log(lsINFO) << "applyTransaction: bad sequence for pre-paid transaction";
|
||||
cLog(lsINFO) << "applyTransaction: bad sequence for pre-paid transaction";
|
||||
|
||||
terResult = tefPAST_SEQ;
|
||||
}
|
||||
@@ -389,7 +391,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
break;
|
||||
|
||||
case ttINVALID:
|
||||
Log(lsINFO) << "applyTransaction: invalid type";
|
||||
cLog(lsINFO) << "applyTransaction: invalid type";
|
||||
terResult = temINVALID;
|
||||
break;
|
||||
|
||||
@@ -443,7 +445,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
|
||||
transResultInfo(terResult, strToken, strHuman);
|
||||
|
||||
Log(lsINFO) << "applyTransaction: terResult=" << strToken << " : " << terResult << " : " << strHuman;
|
||||
cLog(lsINFO) << "applyTransaction: terResult=" << strToken << " : " << terResult << " : " << strHuman;
|
||||
|
||||
if (isTepPartial(terResult) && isSetBit(params, tapRETRY))
|
||||
{
|
||||
|
||||
@@ -42,6 +42,8 @@
|
||||
#define MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
UniqueNodeList::UniqueNodeList(boost::asio::io_service& io_service) :
|
||||
mdtScoreTimer(io_service),
|
||||
mFetchActive(0),
|
||||
@@ -612,7 +614,7 @@ void UniqueNodeList::processIps(const std::string& strSite, const NewcoinAddress
|
||||
|
||||
std::string strEscNodePublic = sqlEscape(naNodePublic.humanNodePublic());
|
||||
|
||||
Log(lsINFO)
|
||||
cLog(lsDEBUG)
|
||||
<< str(boost::format("Validator: '%s' processing %d ips.")
|
||||
% strSite % ( pmtVecStrIps ? pmtVecStrIps->size() : 0));
|
||||
|
||||
@@ -716,7 +718,7 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str
|
||||
|
||||
if (!boost::regex_match(strReferral, smMatch, reReferral))
|
||||
{
|
||||
Log(lsWARNING) << str(boost::format("Bad validator: syntax error: %s: %s") % strSite % strReferral);
|
||||
cLog(lsWARNING) << str(boost::format("Bad validator: syntax error: %s: %s") % strSite % strReferral);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -727,7 +729,7 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str
|
||||
if (naValidator.setSeedGeneric(strRefered))
|
||||
{
|
||||
|
||||
Log(lsWARNING) << str(boost::format("Bad validator: domain or public key required: %s %s") % strRefered % strComment);
|
||||
cLog(lsWARNING) << str(boost::format("Bad validator: domain or public key required: %s %s") % strRefered % strComment);
|
||||
}
|
||||
else if (naValidator.setNodePublic(strRefered))
|
||||
{
|
||||
@@ -735,7 +737,7 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str
|
||||
// XXX Schedule for CAS lookup.
|
||||
nodeAddPublic(naValidator, vsWhy, strComment);
|
||||
|
||||
Log(lsINFO) << str(boost::format("Node Public: %s %s") % strRefered % strComment);
|
||||
cLog(lsINFO) << str(boost::format("Node Public: %s %s") % strRefered % strComment);
|
||||
|
||||
if (naNodePublic.isValid())
|
||||
vstrValues.push_back(str(boost::format("('%s',%d,'%s')") % strNodePublic % iValues % naValidator.humanNodePublic()));
|
||||
@@ -747,7 +749,7 @@ int UniqueNodeList::processValidators(const std::string& strSite, const std::str
|
||||
// A domain: need to look it up.
|
||||
nodeAddDomain(strRefered, vsWhy, strComment);
|
||||
|
||||
Log(lsINFO) << str(boost::format("Node Domain: %s %s") % strRefered % strComment);
|
||||
cLog(lsINFO) << str(boost::format("Node Domain: %s %s") % strRefered % strComment);
|
||||
|
||||
if (naNodePublic.isValid())
|
||||
vstrValues.push_back(str(boost::format("('%s',%d,%s)") % strNodePublic % iValues % sqlEscape(strRefered)));
|
||||
@@ -1577,7 +1579,7 @@ void UniqueNodeList::nodeBootstrap()
|
||||
// Always merge in the file specified in the config.
|
||||
if (!theConfig.UNL_DEFAULT.empty())
|
||||
{
|
||||
Log(lsINFO) << "Bootstrapping UNL: loading from unl_default.";
|
||||
cLog(lsINFO) << "Bootstrapping UNL: loading from unl_default.";
|
||||
|
||||
bLoaded = nodeLoad(theConfig.UNL_DEFAULT);
|
||||
}
|
||||
@@ -1585,7 +1587,7 @@ void UniqueNodeList::nodeBootstrap()
|
||||
// If never loaded anything try the current directory.
|
||||
if (!bLoaded && theConfig.UNL_DEFAULT.empty())
|
||||
{
|
||||
Log(lsINFO) << "Bootstrapping UNL: loading from '" VALIDATORS_FILE_NAME "'.";
|
||||
cLog(lsINFO) << "Bootstrapping UNL: loading from '" VALIDATORS_FILE_NAME "'.";
|
||||
|
||||
bLoaded = nodeLoad(VALIDATORS_FILE_NAME);
|
||||
}
|
||||
@@ -1595,7 +1597,7 @@ void UniqueNodeList::nodeBootstrap()
|
||||
{
|
||||
NewcoinAddress naInvalid; // Don't want a referrer on added entries.
|
||||
|
||||
Log(lsINFO) << "Bootstrapping UNL: loading from " CONFIG_FILE_NAME ".";
|
||||
cLog(lsINFO) << "Bootstrapping UNL: loading from " CONFIG_FILE_NAME ".";
|
||||
|
||||
if (processValidators("local", CONFIG_FILE_NAME, naInvalid, vsConfig, &theConfig.VALIDATORS))
|
||||
bLoaded = true;
|
||||
@@ -1603,7 +1605,7 @@ void UniqueNodeList::nodeBootstrap()
|
||||
|
||||
if (!bLoaded)
|
||||
{
|
||||
Log(lsINFO) << "Bootstrapping UNL: loading from " << theConfig.VALIDATORS_SITE << ".";
|
||||
cLog(lsINFO) << "Bootstrapping UNL: loading from " << theConfig.VALIDATORS_SITE << ".";
|
||||
|
||||
nodeNetwork();
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "LedgerTiming.h"
|
||||
#include "Log.h"
|
||||
|
||||
// #define VC_DEBUG
|
||||
SETUP_LOG();
|
||||
|
||||
bool ValidationCollection::addValidation(const SerializedValidation::pointer& val)
|
||||
{
|
||||
@@ -21,9 +21,14 @@ bool ValidationCollection::addValidation(const SerializedValidation::pointer& va
|
||||
if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL)))
|
||||
isCurrent = true;
|
||||
else
|
||||
Log(lsWARNING) << "Received stale validation now=" << now << ", close=" << valClose;
|
||||
{
|
||||
cLog(lsWARNING) << "Received stale validation now=" << now << ", close=" << valClose;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cLog(lsINFO) << "Node " << signer.humanNodePublic() << " not in UNL";
|
||||
}
|
||||
else Log(lsINFO) << "Node " << signer.humanNodePublic() << " not in UNL";
|
||||
|
||||
uint256 hash = val->getLedgerHash();
|
||||
uint160 node = signer.getNodeID();
|
||||
@@ -49,7 +54,7 @@ bool ValidationCollection::addValidation(const SerializedValidation::pointer& va
|
||||
}
|
||||
}
|
||||
|
||||
Log(lsINFO) << "Val for " << hash << " from " << signer.humanNodePublic()
|
||||
cLog(lsINFO) << "Val for " << hash << " from " << signer.humanNodePublic()
|
||||
<< " added " << (val->isTrusted() ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale");
|
||||
return isCurrent;
|
||||
}
|
||||
@@ -84,9 +89,7 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
||||
isTrusted = false;
|
||||
else
|
||||
{
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: Untrusted due to time " << ledger;
|
||||
#endif
|
||||
cLog(lsTRACE) << "VC: Untrusted due to time " << ledger;
|
||||
}
|
||||
}
|
||||
if (isTrusted)
|
||||
@@ -95,9 +98,7 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
||||
++untrusted;
|
||||
}
|
||||
}
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
|
||||
#endif
|
||||
cLog(lsTRACE) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
|
||||
}
|
||||
|
||||
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
|
||||
|
||||
191
src/WSDoor.cpp
191
src/WSDoor.cpp
@@ -5,7 +5,6 @@
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include "NetworkOPs.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <iostream>
|
||||
@@ -60,14 +59,15 @@ protected:
|
||||
|
||||
WSServerHandler<websocketpp::WSDOOR_SERVER>* mHandler;
|
||||
connection_ptr mConnection;
|
||||
NetworkOPs& mNetwork;
|
||||
|
||||
public:
|
||||
WSConnection()
|
||||
: mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)),
|
||||
mConnection(connection_ptr()) { ; }
|
||||
// WSConnection()
|
||||
// : mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)),
|
||||
// mConnection(connection_ptr()) { ; }
|
||||
|
||||
WSConnection(WSServerHandler<websocketpp::WSDOOR_SERVER>* wshpHandler, connection_ptr cpConnection)
|
||||
: mHandler(wshpHandler), mConnection(cpConnection) { ; }
|
||||
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()) { ; }
|
||||
|
||||
virtual ~WSConnection();
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
void doLedgerClosed(Json::Value& jvResult, const Json::Value& jvRequest);
|
||||
void doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvRequest);
|
||||
void doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest);
|
||||
void doSubmit(Json::Value& jvResult, const Json::Value& jvRequest);
|
||||
|
||||
// Streaming Commands
|
||||
void doAccountInfoSubscribe(Json::Value& jvResult, const Json::Value& jvRequest);
|
||||
@@ -305,6 +306,7 @@ Json::Value WSConnection::invokeCommand(const Json::Value& jvRequest)
|
||||
{ "ledger_closed", &WSConnection::doLedgerClosed },
|
||||
{ "ledger_current", &WSConnection::doLedgerCurrent },
|
||||
{ "ledger_entry", &WSConnection::doLedgerEntry },
|
||||
{ "submit", &WSConnection::doSubmit },
|
||||
|
||||
// Streaming commands:
|
||||
{ "account_info_subscribe", &WSConnection::doAccountInfoSubscribe },
|
||||
@@ -422,7 +424,7 @@ void WSConnection::doAccountInfoSubscribe(Json::Value& jvResult, const Json::Val
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
theApp->getOPs().subAccountInfo(this, usnaAccoundIds);
|
||||
mNetwork.subAccountInfo(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,7 +456,7 @@ void WSConnection::doAccountInfoUnsubscribe(Json::Value& jvResult, const Json::V
|
||||
mSubAccountInfo.erase(naAccountID);
|
||||
}
|
||||
|
||||
theApp->getOPs().unsubAccountInfo(this, usnaAccoundIds);
|
||||
mNetwork.unsubAccountInfo(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -486,7 +488,7 @@ void WSConnection::doAccountTransactionSubscribe(Json::Value& jvResult, const Js
|
||||
mSubAccountTransaction.insert(naAccountID);
|
||||
}
|
||||
|
||||
theApp->getOPs().subAccountTransaction(this, usnaAccoundIds);
|
||||
mNetwork.subAccountTransaction(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -518,14 +520,14 @@ void WSConnection::doAccountTransactionUnsubscribe(Json::Value& jvResult, const
|
||||
mSubAccountTransaction.erase(naAccountID);
|
||||
}
|
||||
|
||||
theApp->getOPs().unsubAccountTransaction(this, usnaAccoundIds);
|
||||
mNetwork.unsubAccountTransaction(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerAccountsSubcribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().subLedgerAccounts(this))
|
||||
if (!mNetwork.subLedgerAccounts(this))
|
||||
{
|
||||
jvResult["error"] = "ledgerAccountsSubscribed";
|
||||
}
|
||||
@@ -533,7 +535,7 @@ void WSConnection::doLedgerAccountsSubcribe(Json::Value& jvResult, const Json::V
|
||||
|
||||
void WSConnection::doLedgerAccountsUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().unsubLedgerAccounts(this))
|
||||
if (!mNetwork.unsubLedgerAccounts(this))
|
||||
{
|
||||
jvResult["error"] = "ledgerAccountsNotSubscribed";
|
||||
}
|
||||
@@ -541,20 +543,20 @@ void WSConnection::doLedgerAccountsUnsubscribe(Json::Value& jvResult, const Json
|
||||
|
||||
void WSConnection::doLedgerClosed(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
uint256 uLedger = theApp->getOPs().getClosedLedger();
|
||||
uint256 uLedger = mNetwork.getClosedLedger();
|
||||
|
||||
jvResult["ledger_closed_index"] = theApp->getOPs().getLedgerID(uLedger);
|
||||
jvResult["ledger_closed_index"] = mNetwork.getLedgerID(uLedger);
|
||||
jvResult["ledger_closed"] = uLedger.ToString();
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerCurrent(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
jvResult["ledger_current_index"] = theApp->getOPs().getCurrentLedgerID();
|
||||
jvResult["ledger_current_index"] = mNetwork.getCurrentLedgerID();
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
NetworkOPs& noNetwork = theApp->getOPs();
|
||||
NetworkOPs& noNetwork = mNetwork;
|
||||
uint256 uLedger = jvRequest.isMember("ledger") ? uint256(jvRequest["ledger"].asString()) : 0;
|
||||
uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0;
|
||||
|
||||
@@ -781,7 +783,7 @@ void WSConnection::doLedgerEntry(Json::Value& jvResult, const Json::Value& jvReq
|
||||
|
||||
void WSConnection::doServerSubscribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().subLedger(this))
|
||||
if (!mNetwork.subLedger(this))
|
||||
{
|
||||
jvResult["error"] = "serverSubscribed";
|
||||
}
|
||||
@@ -792,22 +794,169 @@ void WSConnection::doServerSubscribe(Json::Value& jvResult, const Json::Value& j
|
||||
|
||||
// XXX Make sure these values are available before returning them.
|
||||
// XXX return connected status.
|
||||
jvResult["ledger_closed"] = theApp->getOPs().getClosedLedger().ToString();
|
||||
jvResult["ledger_current_index"] = theApp->getOPs().getCurrentLedgerID();
|
||||
jvResult["ledger_closed"] = mNetwork.getClosedLedger().ToString();
|
||||
jvResult["ledger_current_index"] = mNetwork.getCurrentLedgerID();
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doServerUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().unsubLedger(this))
|
||||
if (!mNetwork.unsubLedger(this))
|
||||
{
|
||||
jvResult["error"] = "serverNotSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Current requires secret. Allow signed transaction as an alternative.
|
||||
void WSConnection::doSubmit(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
NewcoinAddress naAccount;
|
||||
|
||||
if (!jvRequest.isMember("transaction"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundTransaction";
|
||||
}
|
||||
else if (!jvRequest["transaction"].isMember("Account"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundAccount";
|
||||
}
|
||||
else if (!naAccount.setAccountID(jvRequest["transaction"]["Account"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}
|
||||
else if (!jvRequest.isMember("secret"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundSecret";
|
||||
}
|
||||
else
|
||||
{
|
||||
Ledger::pointer lpCurrent = mNetwork.getCurrentLedger();
|
||||
SLE::pointer sleAccountRoot = mNetwork.getSLE(lpCurrent, Ledger::getAccountRootIndex(naAccount.getAccountID()));
|
||||
|
||||
if (!sleAccountRoot)
|
||||
{
|
||||
// XXX Ignore transactions for accounts not created.
|
||||
|
||||
jvResult["error"] = "accountNotFound";
|
||||
return;
|
||||
}
|
||||
|
||||
bool bHaveAuthKey = false;
|
||||
NewcoinAddress naAuthorizedPublic;
|
||||
#if 0
|
||||
|
||||
if (sleAccountRoot->isFieldPresent(sfAuthorizedKey))
|
||||
{
|
||||
naAuthorizedPublic = mLedgerEntry->getFieldAccount(sfAuthorizedKey);
|
||||
// Json::Value obj = getMasterGenerator(uLedger, naRegularSeed, naMasterGenerator);
|
||||
}
|
||||
#endif
|
||||
|
||||
NewcoinAddress naSecret = NewcoinAddress::createSeedGeneric(jvRequest["secret"].asString());
|
||||
NewcoinAddress naMasterGenerator = NewcoinAddress::createGeneratorPublic(naSecret);
|
||||
|
||||
// Find the index of Account from the master generator, so we can generate the public and private keys.
|
||||
NewcoinAddress naMasterAccountPublic;
|
||||
unsigned int iIndex = 0;
|
||||
bool bFound = false;
|
||||
|
||||
// Don't look at ledger entries to determine if the account exists. Don't want to leak to thin server that these accounts are
|
||||
// related.
|
||||
while (!bFound && iIndex != theConfig.ACCOUNT_PROBE_MAX)
|
||||
{
|
||||
naMasterAccountPublic.setAccountPublic(naMasterGenerator, iIndex);
|
||||
|
||||
Log(lsWARNING) << "authorize: " << iIndex << " : " << naMasterAccountPublic.humanAccountID() << " : " << naAccount.humanAccountID();
|
||||
|
||||
bFound = naAccount.getAccountID() == naMasterAccountPublic.getAccountID();
|
||||
if (!bFound)
|
||||
++iIndex;
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
jvResult["error"] = "accountNotMatched";
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the generator to determine the associated public and private keys.
|
||||
NewcoinAddress naGenerator = NewcoinAddress::createGeneratorPublic(naSecret);
|
||||
NewcoinAddress naAccountPublic = NewcoinAddress::createAccountPublic(naGenerator, iIndex);
|
||||
NewcoinAddress naAccountPrivate = NewcoinAddress::createAccountPrivate(naGenerator, naSecret, iIndex);
|
||||
|
||||
if (bHaveAuthKey
|
||||
// The generated pair must match authorized...
|
||||
&& naAuthorizedPublic.getAccountID() != naAccountPublic.getAccountID()
|
||||
// ... or the master key must have been used.
|
||||
&& naAccount.getAccountID() != naAccountPublic.getAccountID())
|
||||
{
|
||||
// std::cerr << "iIndex: " << iIndex << std::endl;
|
||||
// std::cerr << "sfAuthorizedKey: " << strHex(asSrc->getAuthorizedKey().getAccountID()) << std::endl;
|
||||
// std::cerr << "naAccountPublic: " << strHex(naAccountPublic.getAccountID()) << std::endl;
|
||||
|
||||
jvResult["error"] = "passwordChanged";
|
||||
return;
|
||||
}
|
||||
|
||||
std::auto_ptr<STObject> sopTrans;
|
||||
|
||||
try
|
||||
{
|
||||
sopTrans = STObject::parseJson(jvRequest["transaction"]);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
jvResult["error"] = "malformedTransaction";
|
||||
jvResult["error_exception"] = e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
sopTrans->setFieldVL(sfSigningPubKey, naAccountPublic.getAccountPublic());
|
||||
|
||||
SerializedTransaction::pointer stpTrans = boost::make_shared<SerializedTransaction>(*sopTrans);
|
||||
|
||||
stpTrans->sign(naAccountPrivate);
|
||||
|
||||
Transaction::pointer tpTrans;
|
||||
|
||||
try
|
||||
{
|
||||
tpTrans = boost::make_shared<Transaction>(stpTrans, false);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
jvResult["error"] = "internalTransaction";
|
||||
jvResult["error_exception"] = e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
tpTrans = mNetwork.submitTransaction(tpTrans);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
jvResult["error"] = "internalSubmit";
|
||||
jvResult["error_exception"] = e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
jvResult["submitted"] = tpTrans->getJson(0);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
jvResult["error"] = "internalJson";
|
||||
jvResult["error_exception"] = e.what();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().subTransaction(this))
|
||||
if (!mNetwork.subTransaction(this))
|
||||
{
|
||||
jvResult["error"] = "TransactionsSubscribed";
|
||||
}
|
||||
@@ -815,7 +964,7 @@ void WSConnection::doTransactionSubcribe(Json::Value& jvResult, const Json::Valu
|
||||
|
||||
void WSConnection::doTransactionUnsubscribe(Json::Value& jvResult, const Json::Value& jvRequest)
|
||||
{
|
||||
if (!theApp->getOPs().unsubTransaction(this))
|
||||
if (!mNetwork.unsubTransaction(this))
|
||||
{
|
||||
jvResult["error"] = "TransactionsNotSubscribed";
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "uint256.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
//
|
||||
@@ -67,6 +68,16 @@ std::vector<unsigned char> strUnHex(const std::string& strSrc)
|
||||
return strCopy(strTmp);
|
||||
}
|
||||
|
||||
uint64_t uintFromHex(const std::string& strSrc)
|
||||
{
|
||||
uint64_t uValue = 0;
|
||||
|
||||
BOOST_FOREACH(char c, strSrc)
|
||||
uValue = (uValue << 4) | charUnHex(c);
|
||||
|
||||
return uValue;
|
||||
}
|
||||
|
||||
//
|
||||
// Misc string
|
||||
//
|
||||
|
||||
23
src/utils.h
23
src/utils.h
@@ -25,11 +25,22 @@ extern uint64_t be64toh(uint64_t value);
|
||||
extern uint32_t htobe32(uint32_t value);
|
||||
extern uint32_t be32toh(uint32_t value);
|
||||
#elif __APPLE__
|
||||
#define be16toh(x) betoh16(x)
|
||||
#define be32toh(x) betoh32(x)
|
||||
#define be64toh(x) betoh64(x)
|
||||
#define h64tobe(x) htobe64(x)
|
||||
#define h32tobe(x) htobe32(x)
|
||||
#include <libkern/OSByteOrder.h>
|
||||
|
||||
#define htobe16(x) OSSwapHostToBigInt16(x)
|
||||
#define htole16(x) OSSwapHostToLittleInt16(x)
|
||||
#define be16toh(x) OSSwapBigToHostInt16(x)
|
||||
#define le16toh(x) OSSwapLittleToHostInt16(x)
|
||||
|
||||
#define htobe32(x) OSSwapHostToBigInt32(x)
|
||||
#define htole32(x) OSSwapHostToLittleInt32(x)
|
||||
#define be32toh(x) OSSwapBigToHostInt32(x)
|
||||
#define le32toh(x) OSSwapLittleToHostInt32(x)
|
||||
|
||||
#define htobe64(x) OSSwapHostToBigInt64(x)
|
||||
#define htole64(x) OSSwapHostToLittleInt64(x)
|
||||
#define be64toh(x) OSSwapBigToHostInt64(x)
|
||||
#define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -151,6 +162,8 @@ bool isZero(Iterator first, int iSize)
|
||||
int charUnHex(char cDigit);
|
||||
void strUnHex(std::string& strDst, const std::string& strSrc);
|
||||
|
||||
uint64_t uintFromHex(const std::string& strSrc);
|
||||
|
||||
std::vector<unsigned char> strUnHex(const std::string& strSrc);
|
||||
|
||||
std::vector<unsigned char> strCopy(const std::string& strSrc);
|
||||
|
||||
@@ -28,37 +28,37 @@ exports.accounts = {
|
||||
// Users
|
||||
'alice' : {
|
||||
'account' : 'iG1QQv2nh2gi7RCZ1P8YYcBUKCCN633jCn',
|
||||
'passphrase' : 'alice',
|
||||
'secret' : 'alice',
|
||||
},
|
||||
'bob' : {
|
||||
'account' : 'iPMh7Pr9ct699rZUTWaytJUoHcJ7cgyzrK',
|
||||
'passphrase' : 'bob',
|
||||
'secret' : 'bob',
|
||||
},
|
||||
'carol' : {
|
||||
'account' : 'iH4KEcG9dEwGwpn6AyoWK9cZPLL4RLSmWW',
|
||||
'passphrase' : 'carol',
|
||||
'secret' : 'carol',
|
||||
},
|
||||
|
||||
// Nexuses
|
||||
'bitstamp' : {
|
||||
'account' : 'i4jKmc2nQb5yEU6eycefrNKGHTU5NQJASx',
|
||||
'passphrase' : 'bitstamp',
|
||||
'secret' : 'bitstamp',
|
||||
},
|
||||
'mtgox' : {
|
||||
'account' : 'iGrhwhaqU8g7ahwAvTq6rX5ivsfcbgZw6v',
|
||||
'passphrase' : 'mtgox',
|
||||
'secret' : 'mtgox',
|
||||
},
|
||||
|
||||
// Merchants
|
||||
'amazon' : {
|
||||
'account' : 'ihheXqX7bDnXePJeMHhubDDvw2uUTtenPd',
|
||||
'passphrase' : 'amazon',
|
||||
'secret' : 'amazon',
|
||||
},
|
||||
|
||||
// Master account
|
||||
'root' : {
|
||||
'account' : 'iHb9CJAWyB4ij91VRWn96DkukG4bwdtyTh',
|
||||
'passphrase' : 'masterpassphrase',
|
||||
'secret' : 'masterpassphrase',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ Server.method('serverSpawnSync', function() {
|
||||
config.newcoind,
|
||||
[
|
||||
"-a",
|
||||
"-v",
|
||||
"--conf=newcoind.cfg"
|
||||
],
|
||||
{
|
||||
|
||||
@@ -1,17 +1,35 @@
|
||||
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 remote = require("../js/remote.js");
|
||||
var utils = require("../js/utils.js");
|
||||
var config = require("./config.js");
|
||||
|
||||
// How long to wait for server to start.
|
||||
var serverDelay = 1500;
|
||||
|
||||
buster.testRunner.timeout = 5000;
|
||||
|
||||
buster.testCase("Utils", {
|
||||
"hexToString and stringToHex" : {
|
||||
"Even: 123456" : function () {
|
||||
buster.assert.equals("123456", utils.stringToHex(utils.hexToString("123456")));
|
||||
},
|
||||
"Odd: 12345" : function () {
|
||||
buster.assert.equals("012345", utils.stringToHex(utils.hexToString("12345")));
|
||||
},
|
||||
"Under 10: 0" : function () {
|
||||
buster.assert.equals("00", utils.stringToHex(utils.hexToString("0")));
|
||||
},
|
||||
"Under 10: 1" : function () {
|
||||
buster.assert.equals("01", utils.stringToHex(utils.hexToString("1")));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
buster.testCase("Standalone server startup", {
|
||||
"server start and stop": function (done) {
|
||||
"server start and stop" : function (done) {
|
||||
server.start("alpha",
|
||||
function (e) {
|
||||
buster.refute(e);
|
||||
@@ -184,6 +202,16 @@ buster.testCase("Websocket commands", {
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'create account' :
|
||||
function (done) {
|
||||
alpha.send_xns(undefined, 'root', 'alice', 10000, true, function (r) {
|
||||
console.log(r);
|
||||
|
||||
buster.refute(r.error);
|
||||
done();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// vim:sw=2:sts=2:ts=8
|
||||
|
||||
Reference in New Issue
Block a user