diff --git a/SConstruct b/SConstruct
index f944d7799c..83dd04ef4e 100644
--- a/SConstruct
+++ b/SConstruct
@@ -4,6 +4,8 @@
import glob
import platform
+import commands
+import re
OSX = bool(platform.mac_ver()[0])
FreeBSD = bool('FreeBSD' == platform.system())
@@ -23,6 +25,8 @@ env = Environment(
tools = ['default', 'protoc']
)
+GCC_VERSION = re.split('\.', commands.getoutput(env['CXX'] + ' -dumpversion'))
+
# Use clang
#env.Replace(CC = 'clang')
#env.Replace(CXX = 'clang++')
@@ -100,7 +104,10 @@ 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=1'])
-env.Append(CXXFLAGS = ['-O0', '-std=c++11', '-pthread', '-Wno-invalid-offsetof', '-Wformat']+BOOSTFLAGS+DEBUGFLAGS)
+env.Append(CXXFLAGS = ['-O0', '-pthread', '-Wno-invalid-offsetof', '-Wformat']+BOOSTFLAGS+DEBUGFLAGS)
+
+if (GCC_VERSION[0] > 4 or (GCC_VERSION[0] == 4 and GCC_VERSION[1] >= 7)):
+ env.Append(CXXFLAGS = ['-std=c++11'])
if OSX:
env.Append(LINKFLAGS = ['-L/usr/local/opt/openssl/lib'])
diff --git a/bin/browser.js b/bin/browser.js
index ab33850d05..30e83c3c36 100755
--- a/bin/browser.js
+++ b/bin/browser.js
@@ -1,9 +1,9 @@
#!/usr/bin/node
//
-// ledger_header?l=L
+// ledger?l=L
// transaction?h=H
// ledger_entry?l=L&h=H
-// account_root?l=L&a=A
+// account?l=L&a=A
// directory?l=L&dir_root=H&i=I
// directory?l=L&o=A&i=I // owner directory
// offer?l=L&offer=H
@@ -26,22 +26,50 @@ var Remote = require("../src/js/remote.js").Remote;
var program = process.argv[1];
+var httpd_response = function (res, opts) {
+ var self=this;
+
+ res.statusCode = opts.statusCode;
+ res.end(
+ ""
+ + "
Title"
+ + ""
+ + "State:" + self.state
+ + ""
+ + (opts.body || '')
+ + '
'
+ + (opts.url || '')
+ + '
'
+ + ""
+ + ""
+ );
+};
+
+var html_link = function (generic) {
+ return '' + generic + '';
+};
+
// Build a link to a type.
var build_uri = function (params, opts) {
var c;
- if (params.type === 'account_root') {
+ if (params.type === 'account') {
c = {
- pathname: 'account_root',
+ pathname: 'account',
query: {
l: params.ledger,
a: params.account,
},
};
- } else if (params.type === 'ledger_header') {
+ } else if (params.type === 'ledger') {
c = {
- pathname: 'ledger_header',
+ pathname: 'ledger',
query: {
l: params.ledger,
},
@@ -58,9 +86,11 @@ var build_uri = function (params, opts) {
c = {};
}
+ opts = opts || {};
+
c.protocol = "http";
- c.hostname = opts.hostname;
- c.port = opts.port;
+ c.hostname = opts.hostname || self.base.hostname;
+ c.port = opts.port || self.base.port;
return url.format(c);
};
@@ -70,31 +100,137 @@ console.log(link);
return "" + item + "";
};
-var rewrite_object = function (obj, opts) {
- var out = extend({}, obj);
+var rewrite_field = function (type, obj, field, opts) {
+ if (field in obj) {
+ obj[field] = rewrite_type(type, obj[field], opts);
+ }
+};
- if ('ledger_index' in obj) {
- out.ledger_index =
- build_link(
- obj.ledger_index,
- build_uri({
- type: 'ledger_header',
- ledger: obj.ledger_index,
- }, opts)
+var rewrite_type = function (type, obj, opts) {
+ if ('amount' === type) {
+ if ('string' === typeof obj) {
+ // XRP.
+ return '' + obj + '';
+
+ } else {
+ rewrite_field('address', obj, 'issuer', opts);
+
+ return obj;
+ }
+ return build_link(
+ obj,
+ build_uri({
+ type: 'account',
+ account: obj
+ }, opts)
+ );
+ }
+ if ('address' === type) {
+ return build_link(
+ obj,
+ build_uri({
+ type: 'account',
+ account: obj
+ }, opts)
+ );
+ }
+ else if ('ledger' === type) {
+ return build_link(
+ obj,
+ build_uri({
+ type: 'ledger',
+ ledger: obj,
+ }, opts)
+ );
+ }
+ else if ('node' === type) {
+ // A node
+ if ('PreviousTxnID' in obj)
+ obj.PreviousTxnID = rewrite_type('transaction', obj.PreviousTxnID, opts);
+
+ if ('Offer' === obj.LedgerEntryType) {
+ if ('NewFields' in obj) {
+ if ('TakerGets' in obj.NewFields)
+ obj.NewFields.TakerGets = rewrite_type('amount', obj.NewFields.TakerGets, opts);
+
+ if ('TakerPays' in obj.NewFields)
+ obj.NewFields.TakerPays = rewrite_type('amount', obj.NewFields.TakerPays, opts);
+ }
+ }
+
+ obj.LedgerEntryType = '' + obj.LedgerEntryType + '';
+
+ return obj;
+ }
+ else if ('transaction' === type) {
+ // Reference to a transaction.
+ return build_link(
+ obj,
+ build_uri({
+ type: 'transaction',
+ hash: obj
+ }, opts)
);
}
- if ('node' in obj) {
+ return 'ERROR: ' + type;
+};
+
+var rewrite_object = function (obj, opts) {
+ var out = extend({}, obj);
+
+ rewrite_field('address', out, 'Account', opts);
+
+ rewrite_field('ledger', out, 'parent_hash', opts);
+ rewrite_field('ledger', out, 'ledger_index', opts);
+ rewrite_field('ledger', out, 'ledger_current_index', opts);
+ rewrite_field('ledger', out, 'ledger_hash', opts);
+
+ if ('ledger' in obj) {
+ // It's a ledger header.
+ out.ledger = rewrite_object(out.ledger, opts);
+
+ if ('ledger_hash' in out.ledger)
+ out.ledger.ledger_hash = '' + out.ledger.ledger_hash + '';
+
+ delete out.ledger.hash;
+ delete out.ledger.totalCoins;
+ }
+
+ if ('TransactionType' in obj) {
+ // It's a transaction.
+ out.TransactionType = '' + obj.TransactionType + '';
+
+ rewrite_field('amount', out, 'TakerGets', opts);
+ rewrite_field('amount', out, 'TakerPays', opts);
+ rewrite_field('ledger', out, 'inLedger', opts);
+
+ out.meta.AffectedNodes = out.meta.AffectedNodes.map(function (node) {
+ var kind = 'CreatedNode' in node
+ ? 'CreatedNode'
+ : 'ModifiedNode' in node
+ ? 'ModifiedNode'
+ : 'DeletedNode' in node
+ ? 'DeletedNode'
+ : undefined;
+
+ if (kind) {
+ node[kind] = rewrite_type('node', node[kind], opts);
+ }
+ return node;
+ });
+ }
+ else if ('node' in obj && 'LedgerEntryType' in obj.node) {
+ // Its a ledger entry.
+
if (obj.node.LedgerEntryType === 'AccountRoot') {
- out.node.PreviousTxnID =
- build_link(
- obj.node.PreviousTxnID,
- build_uri({
- type: 'transaction',
- hash: obj.node.PreviousTxnID,
- }, opts)
- );
+ out.node.Account = rewrite_type('address', obj.node.Account, opts);
+// out.node.hash = rewrite_type('transaction', obj.node.hash, opts);
+ out.node.PreviousTxnID = rewrite_type('transaction', out.node.PreviousTxnID, opts);
+ out.node.PreviousTxnLgrSeq = rewrite_type('ledger', out.node.PreviousTxnLgrSeq, opts);
}
+
+ out.node.LedgerEntryType = '' + out.node.LedgerEntryType + '';
}
return out;
@@ -109,7 +245,7 @@ else {
var ip = process.argv.length > 4 ? process.argv[4] : "127.0.0.1";
var port = process.argv.length > 5 ? process.argv[5] : "8080";
-console.log("START");
+// console.log("START");
var self = this;
self.base = {
@@ -120,7 +256,7 @@ console.log("START");
var remote = (new Remote({
websocket_ip: ws_ip,
websocket_port: ws_port,
- trace: true
+// trace: true
}))
.on('state', function (m) {
console.log("STATE: %s", m);
@@ -131,7 +267,7 @@ console.log("START");
.connect()
;
-console.log("SERVE");
+// console.log("SERVE");
var server = http.createServer(function (req, res) {
var input = "";
@@ -143,113 +279,101 @@ console.log("SERVE");
});
req.on('end', function () {
- console.log("URL: %s", req.url);
+ // console.log("URL: %s", req.url);
// console.log("HEADERS: %s", JSON.stringify(req.headers, undefined, 2));
var _parsed = url.parse(req.url, true);
var _url = JSON.stringify(_parsed, undefined, 2);
- if (_parsed.pathname === "/account_root") {
+ // console.log("HEADERS: %s", JSON.stringify(_parsed, undefined, 2));
+ if (_parsed.pathname === "/account") {
var request = remote
.request_ledger_entry('account_root')
.ledger_index(-1)
.account_root(_parsed.query.a)
.on('success', function (m) {
- console.log("account_root: %s", JSON.stringify(m, undefined, 2));
+ // console.log("account_root: %s", JSON.stringify(m, undefined, 2));
- res.statusCode = 200;
- res.end(
- ""
- + "Title"
- + ""
- + "State: " + self.state
- + ""
- + ""
- + JSON.stringify(rewrite_object(m, self.base), undefined, 2)
- + "
"
- + ""
- + ""
- );
+ httpd_response(res,
+ {
+ statusCode: 200,
+ url: _url,
+ body: ""
+ + JSON.stringify(rewrite_object(m, self.base), undefined, 2)
+ + "
"
+ });
})
.request();
- } else if (_parsed.pathname === "/ledger_header") {
- var request = remote
- .request_ledger_header()
- .ledger_index(-1)
- .on('success', function (m) {
- console.log("Ledger: %s", JSON.stringify(m, undefined, 2));
+ } else if (_parsed.pathname === "/ledger") {
+ var request = remote
+ .request_ledger(undefined, { expand: true, transactions: true })
+ .on('success', function (m) {
+ // console.log("Ledger: %s", JSON.stringify(m, undefined, 2));
- res.statusCode = 200;
- res.end(
- ""
- + "Title"
- + ""
- + "State: " + self.state
- + ""
- + ""
- + JSON.stringify(m, undefined, 2)
- + "
"
- + ""
- + ""
- );
- })
- .request();
+ httpd_response(res,
+ {
+ statusCode: 200,
+ url: _url,
+ body: ""
+ + JSON.stringify(rewrite_object(m, self.base), undefined, 2)
+ +"
"
+ });
+ })
+
+ if (_parsed.query.l && _parsed.query.l.length === 64) {
+ request.ledger_hash(_parsed.query.l);
+ }
+ else if (_parsed.query.l) {
+ request.ledger_index(Number(_parsed.query.l));
+ }
+ else {
+ request.ledger_index(-1);
+ }
+
+ request.request();
} else if (_parsed.pathname === "/transaction") {
var request = remote
- .request_transaction_entry(_parsed.query.h)
+ .request_tx(_parsed.query.h)
+// .request_transaction_entry(_parsed.query.h)
// .ledger_select(_parsed.query.l)
.on('success', function (m) {
- console.log("transaction: %s", JSON.stringify(m, undefined, 2));
+ // console.log("transaction: %s", JSON.stringify(m, undefined, 2));
- res.statusCode = 200;
- res.end(
- ""
- + "Title"
- + ""
- + "State: " + self.state
- + ""
- + ""
- + JSON.stringify(rewrite_object(m, self.base), undefined, 2)
- + "
"
- + ""
- + ""
- );
+ httpd_response(res,
+ {
+ statusCode: 200,
+ url: _url,
+ body: ""
+ + JSON.stringify(rewrite_object(m, self.base), undefined, 2)
+ +"
"
+ });
+ })
+ .on('error', function (m) {
+ httpd_response(res,
+ {
+ statusCode: 200,
+ url: _url,
+ body: ""
+ + 'ERROR: ' + JSON.stringify(m, undefined, 2)
+ +"
"
+ });
})
.request();
} else {
var test = build_uri({
- type: 'account_root',
+ type: 'account',
ledger: 'closed',
account: 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh',
}, self.base);
- res.statusCode = req.url === "/" ? 200 : 404;
- res.end(
- ""
- + "Title"
- + ""
- + "State: " + self.state
- + ""
- + ""+_url+"
"
- + ""
- + ""
- );
+ httpd_response(res,
+ {
+ statusCode: req.url === "/" ? 200 : 404,
+ url: _url,
+ });
}
});
});
diff --git a/src/cpp/ripple/CallRPC.cpp b/src/cpp/ripple/CallRPC.cpp
index 96d350140c..1d0f009105 100644
--- a/src/cpp/ripple/CallRPC.cpp
+++ b/src/cpp/ripple/CallRPC.cpp
@@ -785,7 +785,7 @@ int commandLineRPC(const std::vector& vCmd)
: vCmd[0],
jvParams, // Parsed, execute.
false,
- boost::bind(callRPCHandler, &jvOutput, _1));
+ BIND_TYPE(callRPCHandler, &jvOutput, P_1));
isService.run(); // This blocks until there is no more outstanding async calls.
@@ -848,7 +848,7 @@ int commandLineRPC(const std::vector& vCmd)
#define RPC_NOTIFY_SECONDS 10
bool responseRPC(
- boost::function callbackFuncP,
+ FUNCTION_TYPE callbackFuncP,
const boost::system::error_code& ecResult, int iStatus, const std::string& strData)
{
if (callbackFuncP)
@@ -886,7 +886,9 @@ bool responseRPC(
}
// Build the request.
-void requestRPC(const std::string& strMethod, const Json::Value& jvParams, const std::map& mHeaders, const std::string& strPath, boost::asio::streambuf& sb, const std::string& strHost)
+void requestRPC(const std::string& strMethod, const Json::Value& jvParams,
+ const std::map& mHeaders, const std::string& strPath,
+ boost::asio::streambuf& sb, const std::string& strHost)
{
cLog(lsDEBUG) << "requestRPC: strPath='" << strPath << "'";
@@ -906,7 +908,7 @@ void callRPC(
const std::string& strUsername, const std::string& strPassword,
const std::string& strPath, const std::string& strMethod,
const Json::Value& jvParams, const bool bSSL,
- boost::function callbackFuncP)
+ FUNCTION_TYPE callbackFuncP)
{
// Connect to localhost
if (!theConfig.QUIET)
@@ -933,15 +935,15 @@ void callRPC(
io_service,
strIp,
iPort,
- boost::bind(
+ BIND_TYPE(
&requestRPC,
strMethod,
jvParams,
mapRequestHeaders,
- strPath, _1, _2),
+ strPath, P_1, P_2),
RPC_REPLY_MAX_BYTES,
boost::posix_time::seconds(RPC_NOTIFY_SECONDS),
- boost::bind(&responseRPC, callbackFuncP, _1, _2, _3));
+ BIND_TYPE(&responseRPC, callbackFuncP, P_1, P_2, P_3));
}
// vim:ts=4
diff --git a/src/cpp/ripple/CallRPC.h b/src/cpp/ripple/CallRPC.h
index adde89f708..5d9a0377fc 100644
--- a/src/cpp/ripple/CallRPC.h
+++ b/src/cpp/ripple/CallRPC.h
@@ -56,7 +56,7 @@ extern void callRPC(
const std::string& strUsername, const std::string& strPassword,
const std::string& strPath, const std::string& strMethod,
const Json::Value& jvParams, const bool bSSL,
- boost::function callbackFuncP = 0);
+ FUNCTION_TYPE callbackFuncP = 0);
#endif
// vim:ts=4
diff --git a/src/cpp/ripple/ConnectionPool.cpp b/src/cpp/ripple/ConnectionPool.cpp
index 89f0d55489..d17f38885e 100644
--- a/src/cpp/ripple/ConnectionPool.cpp
+++ b/src/cpp/ripple/ConnectionPool.cpp
@@ -209,6 +209,12 @@ void ConnectionPool::policyEnforce()
// Enforce policies.
policyLowWater();
+ if (((++mPhase) % 12) == 0)
+ {
+ cLog(lsTRACE) << "Making configured connections";
+ makeConfigured();
+ }
+
// Schedule next enforcement.
mPolicyTimer.expires_at(boost::posix_time::second_clock::universal_time()+boost::posix_time::seconds(POLICY_INTERVAL_SECONDS));
mPolicyTimer.async_wait(boost::bind(&ConnectionPool::policyHandler, this, _1));
@@ -313,11 +319,11 @@ Peer::pointer ConnectionPool::peerConnect(const std::string& strIp, int iPort)
if (ppResult)
{
ppResult->connect(strIp, iPort);
- //cLog(lsINFO) << "Pool: Connecting: " << ADDRESS_SHARED(ppResult) << ": " << strIp << " " << iPort;
+ cLog(lsTRACE) << "Pool: Connecting: " << ADDRESS_SHARED(ppResult) << ": " << strIp << " " << iPort;
}
else
{
- //cLog(lsINFO) << "Pool: Already connected: " << strIp << " " << iPort;
+ cLog(lsTRACE) << "Pool: Already connected: " << strIp << " " << iPort;
}
return ppResult;
@@ -623,6 +629,20 @@ void ConnectionPool::scanHandler(const boost::system::error_code& ecResult)
}
}
+void ConnectionPool::makeConfigured()
+{
+ if (theConfig.RUN_STANDALONE)
+ return;
+
+ BOOST_FOREACH(const std::string& strPeer, theConfig.IPS)
+ {
+ std::string strIP;
+ int iPort;
+ if (parseIpPort(strPeer, strIP, iPort))
+ peerConnect(strIP, iPort);
+ }
+}
+
// Scan ips as per db entries.
void ConnectionPool::scanRefresh()
{
diff --git a/src/cpp/ripple/ConnectionPool.h b/src/cpp/ripple/ConnectionPool.h
index 3d1e3d3a4d..45ba2b6e95 100644
--- a/src/cpp/ripple/ConnectionPool.h
+++ b/src/cpp/ripple/ConnectionPool.h
@@ -18,6 +18,7 @@ class ConnectionPool
private:
boost::recursive_mutex mPeerLock;
uint64 mLastPeer;
+ int mPhase;
typedef std::pair naPeer;
typedef std::pair pipPeer;
@@ -59,7 +60,7 @@ private:
public:
ConnectionPool(boost::asio::io_service& io_service) :
- mLastPeer(0), mScanTimer(io_service), mPolicyTimer(io_service)
+ mLastPeer(0), mPhase(0), mScanTimer(io_service), mPolicyTimer(io_service)
{ ; }
// Begin enforcing connection policy.
@@ -114,6 +115,8 @@ public:
void policyLowWater();
void policyEnforce();
+ // configured connections
+ void makeConfigured();
};
extern void splitIpPort(const std::string& strIpPort, std::string& strIp, int& iPort);
diff --git a/src/cpp/ripple/HttpsClient.cpp b/src/cpp/ripple/HttpsClient.cpp
index 1ae01e19f2..1144d98596 100644
--- a/src/cpp/ripple/HttpsClient.cpp
+++ b/src/cpp/ripple/HttpsClient.cpp
@@ -6,7 +6,6 @@
#include "utils.h"
#include
-#include
#include
#include
#include
@@ -52,9 +51,9 @@ void HttpsClient::makeGet(const std::string& strPath, boost::asio::streambuf& sb
void HttpsClient::httpsRequest(
bool bSSL,
std::deque deqSites,
- boost::function build,
+ FUNCTION_TYPE build,
boost::posix_time::time_duration timeout,
- boost::function complete)
+ FUNCTION_TYPE complete)
{
mSSL = bSSL;
mDeqSites = deqSites;
@@ -70,7 +69,7 @@ void HttpsClient::httpsGet(
std::deque deqSites,
const std::string& strPath,
boost::posix_time::time_duration timeout,
- boost::function complete) {
+ FUNCTION_TYPE complete) {
mComplete = complete;
mTimeout = timeout;
@@ -78,7 +77,7 @@ void HttpsClient::httpsGet(
httpsRequest(
bSSL,
deqSites,
- boost::bind(&HttpsClient::makeGet, shared_from_this(), strPath, _1, _2),
+ BIND_TYPE(&HttpsClient::makeGet, shared_from_this(), strPath, P_1, P_2),
timeout,
complete);
}
@@ -403,7 +402,7 @@ void HttpsClient::httpsGet(
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete) {
+ FUNCTION_TYPE complete) {
boost::shared_ptr client(new HttpsClient(io_service, port, responseMax));
@@ -418,7 +417,7 @@ void HttpsClient::httpsGet(
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete) {
+ FUNCTION_TYPE complete) {
std::deque deqSites(1, strSite);
@@ -432,10 +431,10 @@ void HttpsClient::httpsRequest(
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
- boost::function setRequest,
+ FUNCTION_TYPE setRequest,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete) {
+ FUNCTION_TYPE complete) {
std::deque deqSites(1, strSite);
diff --git a/src/cpp/ripple/HttpsClient.h b/src/cpp/ripple/HttpsClient.h
index d4e89df6c8..909594efe1 100644
--- a/src/cpp/ripple/HttpsClient.h
+++ b/src/cpp/ripple/HttpsClient.h
@@ -8,10 +8,10 @@
#include
#include
#include
-#include
#include
#include "AutoSocket.h"
+#include "utils.h"
//
// Async https client.
@@ -33,8 +33,8 @@ private:
const unsigned short mPort;
int mResponseMax;
int mStatus;
- boost::function mBuild;
- boost::function mComplete;
+ FUNCTION_TYPE mBuild;
+ FUNCTION_TYPE mComplete;
boost::asio::deadline_timer mDeadline;
@@ -76,16 +76,16 @@ public:
void httpsRequest(
bool bSSL,
std::deque deqSites,
- boost::function build,
+ FUNCTION_TYPE build,
boost::posix_time::time_duration timeout,
- boost::function complete);
+ FUNCTION_TYPE complete);
void httpsGet(
bool bSSL,
std::deque deqSites,
const std::string& strPath,
boost::posix_time::time_duration timeout,
- boost::function complete);
+ FUNCTION_TYPE complete);
static void httpsGet(
bool bSSL,
@@ -95,7 +95,7 @@ public:
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete);
+ FUNCTION_TYPE complete);
static void httpsGet(
bool bSSL,
@@ -105,17 +105,17 @@ public:
const std::string& strPath,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete);
+ FUNCTION_TYPE complete);
static void httpsRequest(
bool bSSL,
boost::asio::io_service& io_service,
std::string strSite,
const unsigned short port,
- boost::function build,
+ FUNCTION_TYPE build,
std::size_t responseMax,
boost::posix_time::time_duration timeout,
- boost::function complete);
+ FUNCTION_TYPE complete);
};
#endif
// vim:ts=4
diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp
index 2d689156e0..d9fdab4ca5 100644
--- a/src/cpp/ripple/Ledger.cpp
+++ b/src/cpp/ripple/Ledger.cpp
@@ -421,7 +421,13 @@ void Ledger::saveAcceptedLedger(Job&, bool fromConsensus)
assert(false);
}
- assert (getAccountHash() == mAccountStateMap->getHash());
+ if (getAccountHash() != mAccountStateMap->getHash())
+ {
+ cLog(lsFATAL) << "sAL: " << getAccountHash() << " != " << mAccountStateMap->getHash();
+ cLog(lsFATAL) << "saveAcceptedLedger: seq=" << mLedgerSeq << ", fromcons=" << fromConsensus;
+ assert(false);
+ }
+
assert (getTransHash() == mTransactionMap->getHash());
// Save the ledger header in the hashed object store
@@ -1608,6 +1614,32 @@ uint64 Ledger::scaleFeeLoad(uint64 fee)
return theApp->getFeeTrack().scaleFeeLoad(fee, mBaseFee, mReferenceFeeUnits);
}
+std::vector Ledger::getNeededTransactionHashes(int max)
+{
+ std::vector ret;
+ if (mTransHash.isNonZero())
+ {
+ if (mTransactionMap->getHash().isZero())
+ ret.push_back(mTransHash);
+ else
+ ret = mTransactionMap->getNeededHashes(max);
+ }
+ return ret;
+}
+
+std::vector Ledger::getNeededAccountStateHashes(int max)
+{
+ std::vector ret;
+ if (mAccountHash.isNonZero())
+ {
+ if (mAccountStateMap->getHash().isZero())
+ ret.push_back(mAccountHash);
+ else
+ ret = mAccountStateMap->getNeededHashes(max);
+ }
+ return ret;
+}
+
BOOST_AUTO_TEST_SUITE(quality)
BOOST_AUTO_TEST_CASE( getquality )
diff --git a/src/cpp/ripple/Ledger.h b/src/cpp/ripple/Ledger.h
index c260a0443c..5dda848805 100644
--- a/src/cpp/ripple/Ledger.h
+++ b/src/cpp/ripple/Ledger.h
@@ -222,6 +222,9 @@ public:
static uint256 getLedgerFeatureIndex();
static uint256 getLedgerFeeIndex();
+ std::vector getNeededTransactionHashes(int max);
+ std::vector getNeededAccountStateHashes(int max);
+
// index calculation functions
static uint256 getAccountRootIndex(const uint160& uAccountID);
diff --git a/src/cpp/ripple/LedgerAcquire.cpp b/src/cpp/ripple/LedgerAcquire.cpp
index e6da90f82b..e345dc18ca 100644
--- a/src/cpp/ripple/LedgerAcquire.cpp
+++ b/src/cpp/ripple/LedgerAcquire.cpp
@@ -73,13 +73,21 @@ void PeerSet::TimerEntry(boost::weak_ptr wptr, const boost::system::err
return;
boost::shared_ptr ptr = wptr.lock();
if (ptr)
- theApp->getJobQueue().addJob(jtLEDGER_DATA, "timerEntry",
+ {
+ int jc = theApp->getJobQueue().getJobCountTotal(jtLEDGER_DATA);
+ if (jc > 4)
+ {
+ cLog(lsDEBUG) << "Deferring PeerSet timer due to load";
+ ptr->setTimer();
+ }
+ else theApp->getJobQueue().addJob(jtLEDGER_DATA, "timerEntry",
BIND_TYPE(&PeerSet::TimerJobEntry, P_1, ptr));
+ }
}
void PeerSet::TimerJobEntry(Job&, boost::shared_ptr ptr)
{
- ptr->invokeOnTimer();
+ ptr->invokeOnTimer();
}
bool PeerSet::isActive()
@@ -105,14 +113,9 @@ bool LedgerAcquire::tryLocal()
{
HashedObject::pointer node = theApp->getHashedObjectStore().retrieve(mHash);
if (!node)
- {
- mLedger = theApp->getLedgerMaster().getLedgerByHash(mHash);
- if (!mLedger)
- return false;
- }
- else
- mLedger = boost::make_shared(strCopy(node->getData()), true);
+ return false;
+ mLedger = boost::make_shared(strCopy(node->getData()), true);
if (mLedger->getHash() != mHash)
{ // We know for a fact the ledger can never be acquired
cLog(lsWARNING) << mHash << " cannot be a ledger";
@@ -136,7 +139,7 @@ bool LedgerAcquire::tryLocal()
{
mLedger->peekTransactionMap()->fetchRoot(mLedger->getTransHash());
cLog(lsDEBUG) << "Got root txn map locally";
- std::vector h = mLedger->peekTransactionMap()->getNeededHashes(1);
+ std::vector h = mLedger->getNeededTransactionHashes(1);
if (h.empty())
{
cLog(lsDEBUG) << "Had full txn map locally";
@@ -152,14 +155,17 @@ bool LedgerAcquire::tryLocal()
if (!mHaveState)
{
if (mLedger->getAccountHash().isZero())
+ {
+ cLog(lsFATAL) << "We are acquiring a ledger with a zero account hash";
mHaveState = true;
+ }
else
{
try
{
mLedger->peekAccountStateMap()->fetchRoot(mLedger->getAccountHash());
cLog(lsDEBUG) << "Got root AS map locally";
- std::vector h = mLedger->peekAccountStateMap()->getNeededHashes(1);
+ std::vector h = mLedger->getNeededAccountStateHashes(1);
if (h.empty())
{
cLog(lsDEBUG) << "Had full AS map locally";
@@ -270,6 +276,7 @@ void LedgerAcquire::done()
else
theApp->getMasterLedgerAcquire().logFailure(mHash);
+ // FIXME: We hold the PeerSet lock
for (unsigned int i = 0; i < triggers.size(); ++i)
triggers[i](shared_from_this());
}
@@ -591,7 +598,7 @@ bool LedgerAcquire::takeBase(const std::string& data) // data must not have hash
cLog(lsTRACE) << "got base acquiring ledger " << mHash;
#endif
boost::recursive_mutex::scoped_lock sl(mLock);
- if (mHaveBase)
+ if (mComplete || mFailed || mHaveBase)
return true;
mLedger = boost::make_shared(data, false);
if (mLedger->getHash() != mHash)
@@ -626,7 +633,7 @@ bool LedgerAcquire::takeTxNode(const std::list& nodeIDs,
boost::recursive_mutex::scoped_lock sl(mLock);
if (!mHaveBase)
return false;
- if (mHaveTransactions)
+ if (mHaveTransactions || mFailed)
return true;
std::list::const_iterator nodeIDit = nodeIDs.begin();
@@ -673,7 +680,7 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs,
cLog(lsWARNING) << "Don't have ledger base";
return false;
}
- if (mHaveState)
+ if (mHaveState || mFailed)
return true;
std::list::const_iterator nodeIDit = nodeIDs.begin();
@@ -714,6 +721,8 @@ bool LedgerAcquire::takeAsNode(const std::list& nodeIDs,
bool LedgerAcquire::takeAsRootNode(const std::vector& data, SMAddNode& san)
{
boost::recursive_mutex::scoped_lock sl(mLock);
+ if (mFailed || mHaveState)
+ return true;
if (!mHaveBase)
return false;
AccountStateSF tFilter(mLedger->getLedgerSeq());
@@ -724,6 +733,8 @@ bool LedgerAcquire::takeAsRootNode(const std::vector& data, SMAdd
bool LedgerAcquire::takeTxRootNode(const std::vector& data, SMAddNode& san)
{
boost::recursive_mutex::scoped_lock sl(mLock);
+ if (mFailed || mHaveState)
+ return true;
if (!mHaveBase)
return false;
TransactionStateSF tFilter(mLedger->getLedgerSeq());
@@ -775,13 +786,13 @@ std::vector LedgerAcquire::getNeededHashes()
}
if (!mHaveState)
{
- std::vector v = mLedger->peekAccountStateMap()->getNeededHashes(16);
+ std::vector v = mLedger->getNeededAccountStateHashes(16);
BOOST_FOREACH(const uint256& h, v)
ret.push_back(std::make_pair(ripple::TMGetObjectByHash::otSTATE_NODE, h));
}
if (!mHaveTransactions)
{
- std::vector v = mLedger->peekTransactionMap()->getNeededHashes(16);
+ std::vector v = mLedger->getNeededAccountStateHashes(16);
BOOST_FOREACH(const uint256& h, v)
ret.push_back(std::make_pair(ripple::TMGetObjectByHash::otTRANSACTION_NODE, h));
}
@@ -855,7 +866,7 @@ void LedgerAcquireMaster::gotLedgerData(Job&, boost::shared_ptrpunishPeer(LT_InvalidRequest);
return;
}
diff --git a/src/cpp/ripple/LedgerHistory.cpp b/src/cpp/ripple/LedgerHistory.cpp
index 420b442558..0fe513bd64 100644
--- a/src/cpp/ripple/LedgerHistory.cpp
+++ b/src/cpp/ripple/LedgerHistory.cpp
@@ -31,6 +31,7 @@ void LedgerHistory::addLedger(Ledger::pointer ledger)
void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger, bool fromConsensus)
{
assert(ledger && ledger->isAccepted() && ledger->isImmutable());
+ assert(ledger->peekAccountStateMap()->getHash().isNonZero());
uint256 h(ledger->getHash());
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
mLedgersByHash.canonicalize(h, ledger, true);
diff --git a/src/cpp/ripple/LedgerMaster.cpp b/src/cpp/ripple/LedgerMaster.cpp
index 6aa52fa9be..50e96b3470 100644
--- a/src/cpp/ripple/LedgerMaster.cpp
+++ b/src/cpp/ripple/LedgerMaster.cpp
@@ -316,7 +316,7 @@ void LedgerMaster::resumeAcquiring()
else
{
mCompleteLedgers.clearValue(prevMissing);
- cLog(lsWARNING) << "We have a gap at: " << prevMissing + 1;
+ cLog(lsINFO) << "We have a gap at: " << prevMissing + 1;
}
}
}
@@ -353,6 +353,7 @@ void LedgerMaster::fixMismatch(Ledger::ref ledger)
void LedgerMaster::setFullLedger(Ledger::pointer ledger)
{ // A new ledger has been accepted as part of the trusted chain
cLog(lsDEBUG) << "Ledger " << ledger->getLedgerSeq() << " accepted :" << ledger->getHash();
+ assert(ledger->peekAccountStateMap()->getHash().isNonZero());
boost::recursive_mutex::scoped_lock ml(mLock);
diff --git a/src/cpp/ripple/NetworkOPs.cpp b/src/cpp/ripple/NetworkOPs.cpp
index 67c2a8908e..db8a28c0d5 100644
--- a/src/cpp/ripple/NetworkOPs.cpp
+++ b/src/cpp/ripple/NetworkOPs.cpp
@@ -210,6 +210,7 @@ void NetworkOPs::submitTransaction(Job&, SerializedTransaction::pointer iTrans,
}
}
+ // FIXME: Should submit to job queue
theApp->getIOService().post(boost::bind(&NetworkOPs::processTransaction, this,
boost::make_shared(trans, false), callback));
}
diff --git a/src/cpp/ripple/NetworkOPs.h b/src/cpp/ripple/NetworkOPs.h
index 1fa99064b2..99daf9483d 100644
--- a/src/cpp/ripple/NetworkOPs.h
+++ b/src/cpp/ripple/NetworkOPs.h
@@ -185,7 +185,7 @@ public:
//
// Transaction operations
//
- typedef boost::function stCallback; // must complete immediately
+ typedef FUNCTION_TYPE stCallback; // must complete immediately
void submitTransaction(Job&, SerializedTransaction::pointer, stCallback callback = stCallback());
Transaction::pointer submitTransactionSync(Transaction::ref tpTrans, bool bSubmit=true);
diff --git a/src/cpp/ripple/Peer.cpp b/src/cpp/ripple/Peer.cpp
index 752b9c0e13..e4a418f0f7 100644
--- a/src/cpp/ripple/Peer.cpp
+++ b/src/cpp/ripple/Peer.cpp
@@ -830,7 +830,7 @@ static void checkTransaction(Job&, int flags, SerializedTransaction::pointer stx
else
tx = boost::make_shared(stx, false);
- theApp->getIOService().post(boost::bind(&NetworkOPs::processTransaction, &theApp->getOPs(), tx));
+ theApp->getOPs().processTransaction(tx);
#ifndef TRUST_NETWORK
}
diff --git a/src/cpp/ripple/SHAMapSync.cpp b/src/cpp/ripple/SHAMapSync.cpp
index a06f3a4716..13c482f21e 100644
--- a/src/cpp/ripple/SHAMapSync.cpp
+++ b/src/cpp/ripple/SHAMapSync.cpp
@@ -41,7 +41,7 @@ void SHAMap::getMissingNodes(std::vector& nodeIDs, std::vector& nodeIDs, std::vectorisInner() && !d->isFullBelow()) // we might need children of this node
+ {
+ have_all = false;
stack.push(d);
+ }
}
}
if (have_all)
@@ -111,7 +114,7 @@ std::vector SHAMap::getNeededHashes(int max)
stack.pop();
int base = rand() % 256;
- bool have_all = false;
+ bool have_all = true;
for (int ii = 0; ii < 16; ++ii)
{ // traverse in semi-random order
int branch = (base + ii) % 16;
@@ -124,7 +127,10 @@ std::vector SHAMap::getNeededHashes(int max)
SHAMapTreeNode* d = getNodePointer(childID, childHash);
assert(d);
if (d->isInner() && !d->isFullBelow())
+ {
+ have_all = false;
stack.push(d);
+ }
}
catch (SHAMapMissingNode&)
{ // node is not in the map
diff --git a/src/cpp/ripple/UniqueNodeList.cpp b/src/cpp/ripple/UniqueNodeList.cpp
index 5928fb5a9a..04917f2b88 100644
--- a/src/cpp/ripple/UniqueNodeList.cpp
+++ b/src/cpp/ripple/UniqueNodeList.cpp
@@ -885,7 +885,7 @@ void UniqueNodeList::getValidatorsUrl(const RippleAddress& naNodePublic, section
strPath,
NODE_FILE_BYTES_MAX,
boost::posix_time::seconds(NODE_FETCH_SECONDS),
- boost::bind(&UniqueNodeList::responseValidators, this, strValidatorsUrl, naNodePublic, secSite, strDomain, _1, _2, _3));
+ BIND_TYPE(&UniqueNodeList::responseValidators, this, strValidatorsUrl, naNodePublic, secSite, strDomain, P_1, P_2, P_3));
}
else
{
@@ -1063,7 +1063,7 @@ void UniqueNodeList::fetchProcess(std::string strDomain)
NODE_FILE_PATH,
NODE_FILE_BYTES_MAX,
boost::posix_time::seconds(NODE_FETCH_SECONDS),
- boost::bind(&UniqueNodeList::responseFetch, this, strDomain, _1, _2, _3));
+ BIND_TYPE(&UniqueNodeList::responseFetch, this, strDomain, P_1, P_2, P_3));
}
void UniqueNodeList::fetchTimerHandler(const boost::system::error_code& err)
@@ -1610,7 +1610,7 @@ void UniqueNodeList::nodeNetwork()
theConfig.VALIDATORS_URI,
VALIDATORS_FILE_BYTES_MAX,
boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS),
- boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2, _3));
+ BIND_TYPE(&UniqueNodeList::validatorsResponse, this, P_1, P_2, P_3));
}
}
diff --git a/src/js/index.js b/src/js/index.js
index 175c277500..139c71cb1f 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -4,6 +4,7 @@ exports.Currency = require('./currency').Currency;
exports.UInt160 = require('./amount').UInt160;
exports.Seed = require('./amount').Seed;
exports.Transaction = require('./transaction').Transaction;
+exports.Meta = require('./meta').Meta;
exports.utils = require('./utils');