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
This commit is contained in:
@@ -24,20 +24,18 @@ void AccountItems::fillItems(const uint160& accountID, Ledger::ref ledger)
|
|||||||
uint256 rootIndex = Ledger::getOwnerDirIndex(accountID);
|
uint256 rootIndex = Ledger::getOwnerDirIndex(accountID);
|
||||||
uint256 currentIndex = rootIndex;
|
uint256 currentIndex = rootIndex;
|
||||||
|
|
||||||
LedgerStateParms lspNode = lepNONE;
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
SLE::pointer ownerDir = ledger->getDirNode(lspNode, currentIndex);
|
SLE::pointer ownerDir = ledger->getDirNode(currentIndex);
|
||||||
if (!ownerDir) return;
|
if (!ownerDir) return;
|
||||||
|
|
||||||
STVector256 svOwnerNodes = ownerDir->getFieldV256(sfIndexes);
|
STVector256 svOwnerNodes = ownerDir->getFieldV256(sfIndexes);
|
||||||
|
|
||||||
BOOST_FOREACH(uint256& uNode, svOwnerNodes.peekValue())
|
BOOST_FOREACH(uint256& uNode, svOwnerNodes.peekValue())
|
||||||
{
|
{
|
||||||
SLE::pointer sleCur = ledger->getSLE(uNode);
|
SLE::pointer sleCur = ledger->getSLEi(uNode);
|
||||||
|
|
||||||
AccountItem::pointer item=mOfType->makeItem(accountID, sleCur);
|
AccountItem::pointer item = mOfType->makeItem(accountID, sleCur);
|
||||||
if(item)
|
if(item)
|
||||||
{
|
{
|
||||||
mItems.push_back(item);
|
mItems.push_back(item);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ DatabaseCon::~DatabaseCon()
|
|||||||
|
|
||||||
Application::Application() :
|
Application::Application() :
|
||||||
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
|
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
|
||||||
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300),
|
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), mSLECache("LedgerEntryCache", 4096, 120),
|
||||||
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(),
|
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(),
|
||||||
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
|
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
|
||||||
@@ -301,6 +301,7 @@ void Application::sweep()
|
|||||||
mTempNodeCache.sweep();
|
mTempNodeCache.sweep();
|
||||||
mValidations.sweep();
|
mValidations.sweep();
|
||||||
getMasterLedgerAcquire().sweep();
|
getMasterLedgerAcquire().sweep();
|
||||||
|
mSLECache.sweep();
|
||||||
mSweepTimer.expires_from_now(boost::posix_time::seconds(theConfig.getSize(siSweepInterval)));
|
mSweepTimer.expires_from_now(boost::posix_time::seconds(theConfig.getSize(siSweepInterval)));
|
||||||
mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
|
mSweepTimer.async_wait(boost::bind(&Application::sweep, this));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
class RPCDoor;
|
class RPCDoor;
|
||||||
class PeerDoor;
|
class PeerDoor;
|
||||||
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
|
typedef TaggedCache< uint256, std::vector<unsigned char> > NodeCache;
|
||||||
|
typedef TaggedCache< uint256, SLE > SLECache;
|
||||||
|
|
||||||
class DatabaseCon
|
class DatabaseCon
|
||||||
{
|
{
|
||||||
@@ -60,6 +61,7 @@ class Application
|
|||||||
ValidationCollection mValidations;
|
ValidationCollection mValidations;
|
||||||
SuppressionTable mSuppressions;
|
SuppressionTable mSuppressions;
|
||||||
HashedObjectStore mHashedObjectStore;
|
HashedObjectStore mHashedObjectStore;
|
||||||
|
SLECache mSLECache;
|
||||||
SNTPClient mSNTPClient;
|
SNTPClient mSNTPClient;
|
||||||
JobQueue mJobQueue;
|
JobQueue mJobQueue;
|
||||||
RPCHandler mRPCHandler;
|
RPCHandler mRPCHandler;
|
||||||
@@ -118,6 +120,7 @@ public:
|
|||||||
TXQueue& getTxnQueue() { return mTxnQueue; }
|
TXQueue& getTxnQueue() { return mTxnQueue; }
|
||||||
PeerDoor& getPeerDoor() { return *mPeerDoor; }
|
PeerDoor& getPeerDoor() { return *mPeerDoor; }
|
||||||
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }
|
OrderBookDB& getOrderBookDB() { return mOrderBookDB; }
|
||||||
|
SLECache& getSLECache() { return mSLECache; }
|
||||||
|
|
||||||
|
|
||||||
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
|
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ int Config::getSize(SizedItemName item)
|
|||||||
{
|
{
|
||||||
SizedItem sizeTable[] = {
|
SizedItem sizeTable[] = {
|
||||||
{ siSweepInterval, { 10, 30, 60, 90, 90 } },
|
{ siSweepInterval, { 10, 30, 60, 90, 90 } },
|
||||||
{ siLedgerFetch, { 2, 4, 5, 6, 6 } },
|
{ siLedgerFetch, { 2, 2, 3, 4, 5 } },
|
||||||
{ siValidationsSize, { 256, 256, 512, 1024, 1024 } },
|
{ siValidationsSize, { 256, 256, 512, 1024, 1024 } },
|
||||||
{ siValidationsAge, { 500, 500, 500, 500, 500 } },
|
{ siValidationsAge, { 500, 500, 500, 500, 500 } },
|
||||||
{ siNodeCacheSize, { 8192, 32768, 131072, 1048576, 0 } },
|
{ siNodeCacheSize, { 8192, 32768, 131072, 1048576, 0 } },
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ bool ConnectionPool::savePeer(const std::string& strIp, int iPort, char code)
|
|||||||
|
|
||||||
Peer::pointer ConnectionPool::getPeerById(const uint64& id)
|
Peer::pointer ConnectionPool::getPeerById(const uint64& id)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
const boost::unordered_map<uint64, Peer::pointer>::iterator& it = mPeerIdMap.find(id);
|
const boost::unordered_map<uint64, Peer::pointer>::iterator& it = mPeerIdMap.find(id);
|
||||||
if (it == mPeerIdMap.end())
|
if (it == mPeerIdMap.end())
|
||||||
return Peer::pointer();
|
return Peer::pointer();
|
||||||
@@ -107,7 +107,7 @@ Peer::pointer ConnectionPool::getPeerById(const uint64& id)
|
|||||||
|
|
||||||
bool ConnectionPool::hasPeer(const uint64& id)
|
bool ConnectionPool::hasPeer(const uint64& id)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
return mPeerIdMap.find(id) != mPeerIdMap.end();
|
return mPeerIdMap.find(id) != mPeerIdMap.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ bool ConnectionPool::peerAvailable(std::string& strIp, int& iPort)
|
|||||||
|
|
||||||
// Convert mIpMap (list of open connections) to a vector of "<ip> <port>".
|
// Convert mIpMap (list of open connections) to a vector of "<ip> <port>".
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
vstrIpPort.reserve(mIpMap.size());
|
vstrIpPort.reserve(mIpMap.size());
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ void ConnectionPool::policyHandler(const boost::system::error_code& ecResult)
|
|||||||
int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& msg)
|
int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& msg)
|
||||||
{
|
{
|
||||||
int sentTo = 0;
|
int sentTo = 0;
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
|
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
|
||||||
{
|
{
|
||||||
@@ -254,7 +254,7 @@ int ConnectionPool::relayMessage(Peer* fromPeer, const PackedMessage::pointer& m
|
|||||||
|
|
||||||
void ConnectionPool::relayMessageBut(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
|
void ConnectionPool::relayMessageBut(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
|
||||||
{ // Relay message to all but the specified peers
|
{ // Relay message to all but the specified peers
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
|
BOOST_FOREACH(const vtConMap& pair, mConnectedMap)
|
||||||
{
|
{
|
||||||
@@ -267,7 +267,7 @@ void ConnectionPool::relayMessageBut(const std::set<uint64>& fromPeers, const Pa
|
|||||||
|
|
||||||
void ConnectionPool::relayMessageTo(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
|
void ConnectionPool::relayMessageTo(const std::set<uint64>& fromPeers, const PackedMessage::pointer& msg)
|
||||||
{ // Relay message to the specified peers
|
{ // Relay message to the specified peers
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
BOOST_FOREACH(const uint64& peerID, fromPeers)
|
BOOST_FOREACH(const uint64& peerID, fromPeers)
|
||||||
{
|
{
|
||||||
@@ -305,34 +305,22 @@ Peer::pointer ConnectionPool::peerConnect(const std::string& strIp, int iPort)
|
|||||||
ipPort pipPeer = make_pair(strIp, iPort);
|
ipPort pipPeer = make_pair(strIp, iPort);
|
||||||
Peer::pointer ppResult;
|
Peer::pointer ppResult;
|
||||||
|
|
||||||
boost::unordered_map<ipPort, Peer::pointer>::iterator it;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
if (mIpMap.find(pipPeer) == mIpMap.end())
|
||||||
if ((it = mIpMap.find(pipPeer)) == mIpMap.end())
|
|
||||||
{
|
{
|
||||||
Peer::pointer ppNew(Peer::create(theApp->getIOService(), theApp->getPeerDoor().getSSLContext(),
|
ppResult = Peer::create(theApp->getIOService(), theApp->getPeerDoor().getSSLContext(),
|
||||||
++mLastPeer, false));
|
++mLastPeer, false);
|
||||||
|
|
||||||
// Did not find it. Not already connecting or connected.
|
mIpMap[pipPeer] = ppResult;
|
||||||
ppNew->connect(strIp, iPort);
|
|
||||||
|
|
||||||
mIpMap[pipPeer] = ppNew;
|
|
||||||
|
|
||||||
ppResult = ppNew;
|
|
||||||
// ++miConnectStarting;
|
// ++miConnectStarting;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Found it. Already connected.
|
|
||||||
|
|
||||||
nothing();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ppResult)
|
if (ppResult)
|
||||||
{
|
{
|
||||||
|
ppResult->connect(strIp, iPort);
|
||||||
//cLog(lsINFO) << "Pool: Connecting: " << ADDRESS_SHARED(ppResult) << ": " << strIp << " " << iPort;
|
//cLog(lsINFO) << "Pool: Connecting: " << ADDRESS_SHARED(ppResult) << ": " << strIp << " " << iPort;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -359,7 +347,7 @@ Json::Value ConnectionPool::getPeersJson()
|
|||||||
|
|
||||||
int ConnectionPool::getPeerCount()
|
int ConnectionPool::getPeerCount()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
return mConnectedMap.size();
|
return mConnectedMap.size();
|
||||||
}
|
}
|
||||||
@@ -368,7 +356,7 @@ std::vector<Peer::pointer> ConnectionPool::getPeerVector()
|
|||||||
{
|
{
|
||||||
std::vector<Peer::pointer> ret;
|
std::vector<Peer::pointer> ret;
|
||||||
|
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
ret.reserve(mConnectedMap.size());
|
ret.reserve(mConnectedMap.size());
|
||||||
|
|
||||||
@@ -383,7 +371,7 @@ std::vector<Peer::pointer> ConnectionPool::getPeerVector()
|
|||||||
|
|
||||||
uint64 ConnectionPool::assignPeerId()
|
uint64 ConnectionPool::assignPeerId()
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
return ++mLastPeer;
|
return ++mLastPeer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,7 +390,7 @@ bool ConnectionPool::peerConnected(Peer::ref peer, const RippleAddress& naPeer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
const boost::unordered_map<RippleAddress, Peer::pointer>::iterator& itCm = mConnectedMap.find(naPeer);
|
const boost::unordered_map<RippleAddress, Peer::pointer>::iterator& itCm = mConnectedMap.find(naPeer);
|
||||||
|
|
||||||
if (itCm == mConnectedMap.end())
|
if (itCm == mConnectedMap.end())
|
||||||
@@ -453,7 +441,7 @@ bool ConnectionPool::peerConnected(Peer::ref peer, const RippleAddress& naPeer,
|
|||||||
// We maintain a map of public key to peer for connected and verified peers. Maintain it.
|
// We maintain a map of public key to peer for connected and verified peers. Maintain it.
|
||||||
void ConnectionPool::peerDisconnected(Peer::ref peer, const RippleAddress& naPeer)
|
void ConnectionPool::peerDisconnected(Peer::ref peer, const RippleAddress& naPeer)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
|
|
||||||
if (naPeer.isValid())
|
if (naPeer.isValid())
|
||||||
{
|
{
|
||||||
@@ -556,7 +544,7 @@ void ConnectionPool::peerClosed(Peer::ref peer, const std::string& strIp, int iP
|
|||||||
// Determine if closed peer was redundant.
|
// Determine if closed peer was redundant.
|
||||||
bool bRedundant = true;
|
bool bRedundant = true;
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mPeerLock);
|
boost::recursive_mutex::scoped_lock sl(mPeerLock);
|
||||||
const boost::unordered_map<ipPort, Peer::pointer>::iterator& itIp = mIpMap.find(ipPeer);
|
const boost::unordered_map<ipPort, Peer::pointer>::iterator& itIp = mIpMap.find(ipPeer);
|
||||||
|
|
||||||
if (itIp == mIpMap.end())
|
if (itIp == mIpMap.end())
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
class ConnectionPool
|
class ConnectionPool
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
boost::mutex mPeerLock;
|
boost::recursive_mutex mPeerLock;
|
||||||
uint64 mLastPeer;
|
uint64 mLastPeer;
|
||||||
|
|
||||||
typedef std::pair<RippleAddress, Peer::pointer> naPeer;
|
typedef std::pair<RippleAddress, Peer::pointer> naPeer;
|
||||||
typedef std::pair<ipPort, Peer::pointer> pipPeer;
|
typedef std::pair<ipPort, Peer::pointer> pipPeer;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ JobQueue::JobQueue() : mLastJob(0), mThreadCount(0), mShuttingDown(false)
|
|||||||
mJobLoads[jtTRANSACTION_l].setTargetLatency(100, 500);
|
mJobLoads[jtTRANSACTION_l].setTargetLatency(100, 500);
|
||||||
mJobLoads[jtPROPOSAL_t].setTargetLatency(100, 500);
|
mJobLoads[jtPROPOSAL_t].setTargetLatency(100, 500);
|
||||||
|
|
||||||
mJobLoads[jtCLIENT].setTargetLatency(250, 1000);
|
mJobLoads[jtCLIENT].setTargetLatency(2000, 5000);
|
||||||
mJobLoads[jtPEER].setTargetLatency(200, 1250);
|
mJobLoads[jtPEER].setTargetLatency(200, 1250);
|
||||||
mJobLoads[jtDISK].setTargetLatency(500, 1000);
|
mJobLoads[jtDISK].setTargetLatency(500, 1000);
|
||||||
mJobLoads[jtRPC].setTargetLatency(250, 750);
|
mJobLoads[jtRPC].setTargetLatency(250, 750);
|
||||||
|
|||||||
@@ -200,8 +200,8 @@ AccountState::pointer Ledger::getAccountState(const RippleAddress& accountID)
|
|||||||
// std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl;
|
// std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SHAMapItem::pointer item = mAccountStateMap->peekItem(Ledger::getAccountRootIndex(accountID));
|
SLE::pointer sle = getSLEi(Ledger::getAccountRootIndex(accountID));
|
||||||
if (!item)
|
if (!sle)
|
||||||
{
|
{
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("Ledger:getAccountState: not found: %s: %s")
|
cLog(lsDEBUG) << boost::str(boost::format("Ledger:getAccountState: not found: %s: %s")
|
||||||
% accountID.humanAccountID()
|
% accountID.humanAccountID()
|
||||||
@@ -210,8 +210,6 @@ AccountState::pointer Ledger::getAccountState(const RippleAddress& accountID)
|
|||||||
return AccountState::pointer();
|
return AccountState::pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedLedgerEntry::pointer sle =
|
|
||||||
boost::make_shared<SerializedLedgerEntry>(item->peekSerializer(), item->getTag());
|
|
||||||
if (sle->getType() != ltACCOUNT_ROOT)
|
if (sle->getType() != ltACCOUNT_ROOT)
|
||||||
return AccountState::pointer();
|
return AccountState::pointer();
|
||||||
|
|
||||||
@@ -395,7 +393,7 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event)
|
|||||||
static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';");
|
static boost::format transExists("SELECT Status FROM Transactions WHERE TransID = '%s';");
|
||||||
static boost::format
|
static boost::format
|
||||||
updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c', TxnMeta = %s WHERE TransID = '%s';");
|
updateTx("UPDATE Transactions SET LedgerSeq = %d, Status = '%c', TxnMeta = %s WHERE TransID = '%s';");
|
||||||
static boost::format addLedger("INSERT INTO Ledgers "
|
static boost::format addLedger("INSERT OR REPLACE INTO Ledgers "
|
||||||
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
|
"(LedgerHash,LedgerSeq,PrevHash,TotalCoins,ClosingTime,PrevClosingTime,CloseTimeRes,CloseFlags,"
|
||||||
"AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
|
"AccountSetHash,TransSetHash) VALUES ('%s','%u','%s','%s','%u','%u','%d','%u','%s','%s');");
|
||||||
|
|
||||||
@@ -819,6 +817,7 @@ Json::Value Ledger::getJson(int options)
|
|||||||
{
|
{
|
||||||
Json::Value txns(Json::arrayValue);
|
Json::Value txns(Json::arrayValue);
|
||||||
SHAMapTreeNode::TNType type;
|
SHAMapTreeNode::TNType type;
|
||||||
|
ScopedLock l(mTransactionMap->Lock());
|
||||||
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(type); !!item;
|
for (SHAMapItem::pointer item = mTransactionMap->peekFirstItem(type); !!item;
|
||||||
item = mTransactionMap->peekNextItem(item->getTag(), type))
|
item = mTransactionMap->peekNextItem(item->getTag(), type))
|
||||||
{
|
{
|
||||||
@@ -858,6 +857,7 @@ Json::Value Ledger::getJson(int options)
|
|||||||
if (mAccountStateMap && (bFull || ((options & LEDGER_JSON_DUMP_STATE) != 0)))
|
if (mAccountStateMap && (bFull || ((options & LEDGER_JSON_DUMP_STATE) != 0)))
|
||||||
{
|
{
|
||||||
Json::Value state(Json::arrayValue);
|
Json::Value state(Json::arrayValue);
|
||||||
|
ScopedLock l(mAccountStateMap->Lock());
|
||||||
for (SHAMapItem::pointer item = mAccountStateMap->peekFirstItem(); !!item;
|
for (SHAMapItem::pointer item = mAccountStateMap->peekFirstItem(); !!item;
|
||||||
item = mAccountStateMap->peekNextItem(item->getTag()))
|
item = mAccountStateMap->peekNextItem(item->getTag()))
|
||||||
{
|
{
|
||||||
@@ -954,6 +954,26 @@ SLE::pointer Ledger::getSLE(const uint256& uHash)
|
|||||||
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
return boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLE::pointer Ledger::getSLEi(const uint256& uId)
|
||||||
|
{
|
||||||
|
uint256 hash;
|
||||||
|
|
||||||
|
ScopedLock sl(mAccountStateMap->Lock());
|
||||||
|
|
||||||
|
SHAMapItem::pointer node = mAccountStateMap->peekItem(uId, hash);
|
||||||
|
if (!node)
|
||||||
|
return SLE::pointer();
|
||||||
|
|
||||||
|
SLE::pointer ret = theApp->getSLECache().fetch(hash);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
ret = boost::make_shared<SLE>(node->peekSerializer(), node->getTag());
|
||||||
|
ret->setImmutable();
|
||||||
|
theApp->getSLECache().canonicalize(hash, ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
uint256 Ledger::getFirstLedgerIndex()
|
uint256 Ledger::getFirstLedgerIndex()
|
||||||
{
|
{
|
||||||
SHAMapItem::pointer node = mAccountStateMap->peekFirstItem();
|
SHAMapItem::pointer node = mAccountStateMap->peekFirstItem();
|
||||||
@@ -994,6 +1014,14 @@ uint256 Ledger::getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin)
|
|||||||
return node->getTag();
|
return node->getTag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SLE::pointer Ledger::getASNodeI(const uint256& nodeID, LedgerEntryType let)
|
||||||
|
{
|
||||||
|
SLE::pointer node = getSLEi(nodeID);
|
||||||
|
if (node && (node->getType() != let))
|
||||||
|
node.reset();
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
||||||
LedgerEntryType let )
|
LedgerEntryType let )
|
||||||
{
|
{
|
||||||
@@ -1030,43 +1058,39 @@ SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
|||||||
|
|
||||||
SLE::pointer Ledger::getAccountRoot(const uint160& accountID)
|
SLE::pointer Ledger::getAccountRoot(const uint160& accountID)
|
||||||
{
|
{
|
||||||
LedgerStateParms qry = lepNONE;
|
return getASNodeI(getAccountRootIndex(accountID), ltACCOUNT_ROOT);
|
||||||
|
|
||||||
return getASNode(qry, getAccountRootIndex(accountID), ltACCOUNT_ROOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SLE::pointer Ledger::getAccountRoot(const RippleAddress& naAccountID)
|
SLE::pointer Ledger::getAccountRoot(const RippleAddress& naAccountID)
|
||||||
{
|
{
|
||||||
LedgerStateParms qry = lepNONE;
|
return getASNodeI(getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT);
|
||||||
|
|
||||||
return getASNode(qry, getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Directory
|
// Directory
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex)
|
SLE::pointer Ledger::getDirNode(const uint256& uNodeIndex)
|
||||||
{
|
{
|
||||||
return getASNode(parms, uNodeIndex, ltDIR_NODE);
|
return getASNodeI(uNodeIndex, ltDIR_NODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Generator Map
|
// Generator Map
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID)
|
SLE::pointer Ledger::getGenerator(const uint160& uGeneratorID)
|
||||||
{
|
{
|
||||||
return getASNode(parms, getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP);
|
return getASNodeI(getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Nickname
|
// Nickname
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickname)
|
SLE::pointer Ledger::getNickname(const uint256& uNickname)
|
||||||
{
|
{
|
||||||
return getASNode(parms, uNickname, ltNICKNAME);
|
return getASNodeI(uNickname, ltNICKNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -1074,18 +1098,18 @@ SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickna
|
|||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
SLE::pointer Ledger::getOffer(LedgerStateParms& parms, const uint256& uIndex)
|
SLE::pointer Ledger::getOffer(const uint256& uIndex)
|
||||||
{
|
{
|
||||||
return getASNode(parms, uIndex, ltOFFER);
|
return getASNodeI(uIndex, ltOFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Ripple State
|
// Ripple State
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode)
|
SLE::pointer Ledger::getRippleState(const uint256& uNode)
|
||||||
{
|
{
|
||||||
return getASNode(parms, uNode, ltRIPPLE_STATE);
|
return getASNodeI(uNode, ltRIPPLE_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For an entry put in the 64 bit index or quality.
|
// For an entry put in the 64 bit index or quality.
|
||||||
@@ -1179,7 +1203,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
|
|||||||
int diff = mLedgerSeq - ledgerIndex;
|
int diff = mLedgerSeq - ledgerIndex;
|
||||||
if (diff <= 256)
|
if (diff <= 256)
|
||||||
{
|
{
|
||||||
SLE::pointer hashIndex = getSLE(getLedgerHashIndex());
|
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex());
|
||||||
if (hashIndex)
|
if (hashIndex)
|
||||||
{
|
{
|
||||||
assert(hashIndex->getFieldU32(sfLastLedgerSequence) == (mLedgerSeq - 1));
|
assert(hashIndex->getFieldU32(sfLastLedgerSequence) == (mLedgerSeq - 1));
|
||||||
@@ -1199,7 +1223,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in skiplist
|
// in skiplist
|
||||||
SLE::pointer hashIndex = getSLE(getLedgerHashIndex(ledgerIndex));
|
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex(ledgerIndex));
|
||||||
if (hashIndex)
|
if (hashIndex)
|
||||||
{
|
{
|
||||||
int lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
|
int lastSeq = hashIndex->getFieldU32(sfLastLedgerSequence);
|
||||||
@@ -1219,7 +1243,7 @@ uint256 Ledger::getLedgerHash(uint32 ledgerIndex)
|
|||||||
std::vector< std::pair<uint32, uint256> > Ledger::getLedgerHashes()
|
std::vector< std::pair<uint32, uint256> > Ledger::getLedgerHashes()
|
||||||
{
|
{
|
||||||
std::vector< std::pair<uint32, uint256> > ret;
|
std::vector< std::pair<uint32, uint256> > ret;
|
||||||
SLE::pointer hashIndex = getSLE(getLedgerHashIndex());
|
SLE::pointer hashIndex = getSLEi(getLedgerHashIndex());
|
||||||
if (hashIndex)
|
if (hashIndex)
|
||||||
{
|
{
|
||||||
STVector256 vec = hashIndex->getFieldV256(sfHashes);
|
STVector256 vec = hashIndex->getFieldV256(sfHashes);
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
SLE::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID, LedgerEntryType let);
|
SLE::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID, LedgerEntryType let);
|
||||||
|
|
||||||
|
// returned SLE is immutable
|
||||||
|
SLE::pointer getASNodeI(const uint256& nodeID, LedgerEntryType let);
|
||||||
|
|
||||||
static void incPendingSaves();
|
static void incPendingSaves();
|
||||||
static void decPendingSaves();
|
static void decPendingSaves();
|
||||||
void saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer);
|
void saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer);
|
||||||
@@ -201,7 +204,8 @@ public:
|
|||||||
void pendSave(bool fromConsensus);
|
void pendSave(bool fromConsensus);
|
||||||
|
|
||||||
// next/prev function
|
// next/prev function
|
||||||
SLE::pointer getSLE(const uint256& uHash);
|
SLE::pointer getSLE(const uint256& uHash); // SLE is mutable
|
||||||
|
SLE::pointer getSLEi(const uint256& uHash); // SLE is immutable
|
||||||
uint256 getFirstLedgerIndex();
|
uint256 getFirstLedgerIndex();
|
||||||
uint256 getLastLedgerIndex();
|
uint256 getLastLedgerIndex();
|
||||||
uint256 getNextLedgerIndex(const uint256& uHash); // first node >hash
|
uint256 getNextLedgerIndex(const uint256& uHash); // first node >hash
|
||||||
@@ -230,7 +234,7 @@ public:
|
|||||||
// Generator Map functions
|
// Generator Map functions
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID);
|
SLE::pointer getGenerator(const uint160& uGeneratorID);
|
||||||
|
|
||||||
static uint256 getGeneratorIndex(const uint160& uGeneratorID);
|
static uint256 getGeneratorIndex(const uint160& uGeneratorID);
|
||||||
|
|
||||||
@@ -245,9 +249,8 @@ public:
|
|||||||
NicknameState::pointer getNicknameState(const std::string& strNickname)
|
NicknameState::pointer getNicknameState(const std::string& strNickname)
|
||||||
{ return getNicknameState(getNicknameHash(strNickname)); }
|
{ return getNicknameState(getNicknameHash(strNickname)); }
|
||||||
|
|
||||||
SLE::pointer getNickname(LedgerStateParms& parms, const uint256& uNickname);
|
SLE::pointer getNickname(const uint256& uNickname);
|
||||||
SLE::pointer getNickname(LedgerStateParms& parms, const std::string& strNickname)
|
SLE::pointer getNickname(const std::string& strNickname) { return getNickname(getNicknameHash(strNickname)); }
|
||||||
{ return getNickname(parms, getNicknameHash(strNickname)); }
|
|
||||||
|
|
||||||
static uint256 getNicknameIndex(const uint256& uNickname);
|
static uint256 getNicknameIndex(const uint256& uNickname);
|
||||||
|
|
||||||
@@ -263,16 +266,10 @@ public:
|
|||||||
// Offer functions
|
// Offer functions
|
||||||
//
|
//
|
||||||
|
|
||||||
SLE::pointer getOffer(LedgerStateParms& parms, const uint256& uIndex);
|
SLE::pointer getOffer(const uint256& uIndex);
|
||||||
|
|
||||||
SLE::pointer getOffer(const uint256& uIndex)
|
SLE::pointer getOffer(const uint160& uAccountID, uint32 uSequence)
|
||||||
{
|
{ return getOffer(getOfferIndex(uAccountID, uSequence)); }
|
||||||
LedgerStateParms qry = lepNONE;
|
|
||||||
return getOffer(qry, uIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
SLE::pointer getOffer(LedgerStateParms& parms, const uint160& uAccountID, uint32 uSequence)
|
|
||||||
{ return getOffer(parms, getOfferIndex(uAccountID, uSequence)); }
|
|
||||||
|
|
||||||
// The index of an offer.
|
// The index of an offer.
|
||||||
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
|
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
|
||||||
@@ -293,7 +290,7 @@ public:
|
|||||||
static void ownerDirDescriber(SLE::ref, const uint160& owner);
|
static void ownerDirDescriber(SLE::ref, const uint160& owner);
|
||||||
|
|
||||||
// Return a node: root or normal
|
// Return a node: root or normal
|
||||||
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
|
SLE::pointer getDirNode(const uint256& uNodeIndex);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Quality
|
// Quality
|
||||||
@@ -316,13 +313,7 @@ public:
|
|||||||
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
||||||
{ return getRippleStateIndex(RippleAddress::createAccountID(uiA), RippleAddress::createAccountID(uiB), uCurrency); }
|
{ return getRippleStateIndex(RippleAddress::createAccountID(uiA), RippleAddress::createAccountID(uiB), uCurrency); }
|
||||||
|
|
||||||
SLE::pointer getRippleState(LedgerStateParms& parms, const uint256& uNode);
|
SLE::pointer getRippleState(const uint256& uNode);
|
||||||
|
|
||||||
SLE::pointer getRippleState(const uint256& uNode)
|
|
||||||
{
|
|
||||||
LedgerStateParms qry = lepNONE;
|
|
||||||
return getRippleState(qry, uNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
SLE::pointer getRippleState(const RippleAddress& naA, const RippleAddress& naB, const uint160& uCurrency)
|
SLE::pointer getRippleState(const RippleAddress& naA, const RippleAddress& naB, const uint160& uCurrency)
|
||||||
{ return getRippleState(getRippleStateIndex(naA, naB, uCurrency)); }
|
{ return getRippleState(getRippleStateIndex(naA, naB, uCurrency)); }
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ void PeerSet::TimerEntry(boost::weak_ptr<PeerSet> wptr, const boost::system::err
|
|||||||
{
|
{
|
||||||
if (result == boost::asio::error::operation_aborted)
|
if (result == boost::asio::error::operation_aborted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ScopedLock sl(theApp->getMasterLock());
|
||||||
boost::shared_ptr<PeerSet> ptr = wptr.lock();
|
boost::shared_ptr<PeerSet> ptr = wptr.lock();
|
||||||
if (ptr)
|
if (ptr)
|
||||||
ptr->invokeOnTimer();
|
ptr->invokeOnTimer();
|
||||||
@@ -920,15 +922,21 @@ void LedgerAcquireMaster::sweep()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedgerAcquireMaster::getFetchCount()
|
int LedgerAcquireMaster::getFetchCount(int& timeoutCount)
|
||||||
{
|
{
|
||||||
|
timeoutCount = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
{
|
{
|
||||||
typedef std::pair<uint256, LedgerAcquire::pointer> u256_acq_pair;
|
typedef std::pair<uint256, LedgerAcquire::pointer> u256_acq_pair;
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
BOOST_FOREACH(const u256_acq_pair& it, mLedgers)
|
BOOST_FOREACH(const u256_acq_pair& it, mLedgers)
|
||||||
|
{
|
||||||
if (it.second->isActive())
|
if (it.second->isActive())
|
||||||
|
{
|
||||||
++ret;
|
++ret;
|
||||||
|
timeoutCount += it.second->getTimeouts();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public:
|
|||||||
void dropLedger(const uint256& ledgerHash);
|
void dropLedger(const uint256& ledgerHash);
|
||||||
SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
|
SMAddNode gotLedgerData(ripple::TMLedgerData& packet, Peer::ref);
|
||||||
|
|
||||||
int getFetchCount();
|
int getFetchCount(int& timeoutCount);
|
||||||
void logFailure(const uint256& h) { mRecentFailures.add(h); }
|
void logFailure(const uint256& h) { mRecentFailures.add(h); }
|
||||||
bool isFailure(const uint256& h) { return mRecentFailures.isPresent(h, false); }
|
bool isFailure(const uint256& h) { return mRecentFailures.isPresent(h, false); }
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ LedgerEntryAction LedgerEntrySet::hasEntry(const uint256& index) const
|
|||||||
|
|
||||||
void LedgerEntrySet::entryCache(SLE::ref sle)
|
void LedgerEntrySet::entryCache(SLE::ref sle)
|
||||||
{
|
{
|
||||||
|
assert(sle->isMutable());
|
||||||
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
||||||
if (it == mEntries.end())
|
if (it == mEntries.end())
|
||||||
{
|
{
|
||||||
@@ -128,6 +129,7 @@ void LedgerEntrySet::entryCache(SLE::ref sle)
|
|||||||
|
|
||||||
void LedgerEntrySet::entryCreate(SLE::ref sle)
|
void LedgerEntrySet::entryCreate(SLE::ref sle)
|
||||||
{
|
{
|
||||||
|
assert(sle->isMutable());
|
||||||
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
||||||
if (it == mEntries.end())
|
if (it == mEntries.end())
|
||||||
{
|
{
|
||||||
@@ -161,6 +163,7 @@ void LedgerEntrySet::entryCreate(SLE::ref sle)
|
|||||||
|
|
||||||
void LedgerEntrySet::entryModify(SLE::ref sle)
|
void LedgerEntrySet::entryModify(SLE::ref sle)
|
||||||
{
|
{
|
||||||
|
assert(sle->isMutable());
|
||||||
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
||||||
if (it == mEntries.end())
|
if (it == mEntries.end())
|
||||||
{
|
{
|
||||||
@@ -193,6 +196,7 @@ void LedgerEntrySet::entryModify(SLE::ref sle)
|
|||||||
|
|
||||||
void LedgerEntrySet::entryDelete(SLE::ref sle)
|
void LedgerEntrySet::entryDelete(SLE::ref sle)
|
||||||
{
|
{
|
||||||
|
assert(sle->isMutable());
|
||||||
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
std::map<uint256, LedgerEntrySetEntry>::iterator it = mEntries.find(sle->getIndex());
|
||||||
if (it == mEntries.end())
|
if (it == mEntries.end())
|
||||||
{
|
{
|
||||||
@@ -399,7 +403,7 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result, uint32 index)
|
|||||||
if (type == &sfGeneric)
|
if (type == &sfGeneric)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SLE::pointer origNode = mLedger->getSLE(it.first);
|
SLE::pointer origNode = mLedger->getSLEi(it.first);
|
||||||
SLE::pointer curNode = it.second.mEntry;
|
SLE::pointer curNode = it.second.mEntry;
|
||||||
|
|
||||||
if ((type == &sfModifiedNode) && (*curNode == *origNode))
|
if ((type == &sfModifiedNode) && (*curNode == *origNode))
|
||||||
|
|||||||
@@ -180,7 +180,10 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (theApp->getMasterLedgerAcquire().isFailure(ledgerHash))
|
if (theApp->getMasterLedgerAcquire().isFailure(ledgerHash))
|
||||||
|
{
|
||||||
|
cLog(lsTRACE) << "Already failed to acquire " << ledgerSeq;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash);
|
mMissingLedger = theApp->getMasterLedgerAcquire().findCreate(ledgerHash);
|
||||||
if (mMissingLedger->isComplete())
|
if (mMissingLedger->isComplete())
|
||||||
@@ -203,20 +206,28 @@ bool LedgerMaster::acquireMissingLedger(Ledger::ref origLedger, const uint256& l
|
|||||||
theApp->getIOService().post(boost::bind(&LedgerMaster::missingAcquireComplete, this, mMissingLedger));
|
theApp->getIOService().post(boost::bind(&LedgerMaster::missingAcquireComplete, this, mMissingLedger));
|
||||||
}
|
}
|
||||||
|
|
||||||
int fetch = theConfig.getSize(siLedgerFetch);
|
int fetchMax = theConfig.getSize(siLedgerFetch);
|
||||||
if (theApp->getMasterLedgerAcquire().getFetchCount() < fetch)
|
int timeoutCount;
|
||||||
{
|
int fetchCount = theApp->getMasterLedgerAcquire().getFetchCount(timeoutCount);
|
||||||
int count = 0;
|
|
||||||
typedef std::pair<uint32, uint256> u_pair;
|
|
||||||
|
|
||||||
std::vector<u_pair> vec = origLedger->getLedgerHashes();
|
if (fetchCount < fetchMax)
|
||||||
BOOST_REVERSE_FOREACH(const u_pair& it, vec)
|
{
|
||||||
|
if (timeoutCount > 2)
|
||||||
{
|
{
|
||||||
if ((count < fetch) && (it.first < ledgerSeq) &&
|
cLog(lsDEBUG) << "Not acquiring due to timeouts";
|
||||||
!mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second))
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typedef std::pair<uint32, uint256> u_pair;
|
||||||
|
std::vector<u_pair> vec = origLedger->getLedgerHashes();
|
||||||
|
BOOST_REVERSE_FOREACH(const u_pair& it, vec)
|
||||||
{
|
{
|
||||||
++count;
|
if ((fetchCount < fetchMax) && (it.first < ledgerSeq) &&
|
||||||
theApp->getMasterLedgerAcquire().findCreate(it.second);
|
!mCompleteLedgers.hasValue(it.first) && !theApp->getMasterLedgerAcquire().find(it.second))
|
||||||
|
{
|
||||||
|
++fetchCount;
|
||||||
|
theApp->getMasterLedgerAcquire().findCreate(it.second);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,7 +260,7 @@ bool LedgerMaster::shouldAcquire(uint32 currentLedger, uint32 ledgerHistory, uin
|
|||||||
if (candidateLedger >= currentLedger)
|
if (candidateLedger >= currentLedger)
|
||||||
ret = true;
|
ret = true;
|
||||||
else ret = (currentLedger - candidateLedger) <= ledgerHistory;
|
else ret = (currentLedger - candidateLedger) <= ledgerHistory;
|
||||||
cLog(lsTRACE) << "Missing ledger " << candidateLedger << (ret ? " will" : " will NOT") << " be acquired";
|
cLog(lsTRACE) << "Missing ledger " << candidateLedger << (ret ? " should" : " should NOT") << " be acquired";
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +373,10 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
|||||||
if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
if (!mCompleteLedgers.hasValue(ledger->getLedgerSeq() - 1))
|
||||||
{
|
{
|
||||||
if (!shouldAcquire(mCurrentLedger->getLedgerSeq(), theConfig.LEDGER_HISTORY, ledger->getLedgerSeq() - 1))
|
if (!shouldAcquire(mCurrentLedger->getLedgerSeq(), theConfig.LEDGER_HISTORY, ledger->getLedgerSeq() - 1))
|
||||||
|
{
|
||||||
|
cLog(lsTRACE) << "Don't need any ledgers";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
cLog(lsDEBUG) << "We need the ledger before the ledger we just accepted: " << ledger->getLedgerSeq() - 1;
|
cLog(lsDEBUG) << "We need the ledger before the ledger we just accepted: " << ledger->getLedgerSeq() - 1;
|
||||||
acquireMissingLedger(ledger, ledger->getParentHash(), ledger->getLedgerSeq() - 1);
|
acquireMissingLedger(ledger, ledger->getParentHash(), ledger->getLedgerSeq() - 1);
|
||||||
}
|
}
|
||||||
@@ -387,6 +401,8 @@ void LedgerMaster::setFullLedger(Ledger::ref ledger)
|
|||||||
cLog(lsWARNING) << "We have a gap we can't fix: " << prevMissing + 1;
|
cLog(lsWARNING) << "We have a gap we can't fix: " << prevMissing + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
cLog(lsTRACE) << "Shouldn't acquire";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ bool LoadFeeTrack::lowerLocalFee()
|
|||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
uint32 origFee = mLocalTxnLoadFee;
|
uint32 origFee = mLocalTxnLoadFee;
|
||||||
|
|
||||||
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/16th
|
mLocalTxnLoadFee -= (mLocalTxnLoadFee / lftFeeDecFraction ); // reduce by 1/4
|
||||||
|
|
||||||
if (mLocalTxnLoadFee < lftNormalFee)
|
if (mLocalTxnLoadFee < lftNormalFee)
|
||||||
mLocalTxnLoadFee = lftNormalFee;
|
mLocalTxnLoadFee = lftNormalFee;
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ protected:
|
|||||||
|
|
||||||
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
|
static const int lftNormalFee = 256; // 256 is the minimum/normal load factor
|
||||||
static const int lftFeeIncFraction = 16; // increase fee by 1/16
|
static const int lftFeeIncFraction = 16; // increase fee by 1/16
|
||||||
static const int lftFeeDecFraction = 16; // decrease fee by 1/16
|
static const int lftFeeDecFraction = 4; // decrease fee by 1/4
|
||||||
static const int lftFeeMax = lftNormalFee * 1000000;
|
static const int lftFeeMax = lftNormalFee * 1000000;
|
||||||
|
|
||||||
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||||
|
|||||||
@@ -455,12 +455,9 @@ AccountState::pointer NetworkOPs::getAccountState(Ledger::ref lrLedger, const Ri
|
|||||||
|
|
||||||
SLE::pointer NetworkOPs::getGenerator(Ledger::ref lrLedger, const uint160& uGeneratorID)
|
SLE::pointer NetworkOPs::getGenerator(Ledger::ref lrLedger, const uint160& uGeneratorID)
|
||||||
{
|
{
|
||||||
LedgerStateParms qry = lepNONE;
|
|
||||||
|
|
||||||
if (!lrLedger)
|
if (!lrLedger)
|
||||||
return SLE::pointer();
|
return SLE::pointer();
|
||||||
else
|
return lrLedger->getGenerator(uGeneratorID);
|
||||||
return lrLedger->getGenerator(qry, uGeneratorID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -475,8 +472,7 @@ STVector256 NetworkOPs::getDirNodeInfo(
|
|||||||
uint64& uNodeNext)
|
uint64& uNodeNext)
|
||||||
{
|
{
|
||||||
STVector256 svIndexes;
|
STVector256 svIndexes;
|
||||||
LedgerStateParms lspNode = lepNONE;
|
SLE::pointer sleNode = lrLedger->getDirNode(uNodeIndex);
|
||||||
SLE::pointer sleNode = lrLedger->getDirNode(lspNode, uNodeIndex);
|
|
||||||
|
|
||||||
if (sleNode)
|
if (sleNode)
|
||||||
{
|
{
|
||||||
@@ -524,8 +520,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
|
|||||||
|
|
||||||
uint256 uRootIndex = lpLedger->getOwnerDirIndex(naAccount.getAccountID());
|
uint256 uRootIndex = lpLedger->getOwnerDirIndex(naAccount.getAccountID());
|
||||||
|
|
||||||
LedgerStateParms lspNode = lepNONE;
|
SLE::pointer sleNode = lpLedger->getDirNode(uRootIndex);
|
||||||
SLE::pointer sleNode = lpLedger->getDirNode(lspNode, uRootIndex);
|
|
||||||
|
|
||||||
if (sleNode)
|
if (sleNode)
|
||||||
{
|
{
|
||||||
@@ -538,7 +533,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
|
|||||||
|
|
||||||
BOOST_FOREACH(const uint256& uDirEntry, vuiIndexes)
|
BOOST_FOREACH(const uint256& uDirEntry, vuiIndexes)
|
||||||
{
|
{
|
||||||
SLE::pointer sleCur = lpLedger->getSLE(uDirEntry);
|
SLE::pointer sleCur = lpLedger->getSLEi(uDirEntry);
|
||||||
|
|
||||||
switch (sleCur->getType())
|
switch (sleCur->getType())
|
||||||
{
|
{
|
||||||
@@ -569,9 +564,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
|
|||||||
uNodeDir = sleNode->getFieldU64(sfIndexNext);
|
uNodeDir = sleNode->getFieldU64(sfIndexNext);
|
||||||
if (uNodeDir)
|
if (uNodeDir)
|
||||||
{
|
{
|
||||||
lspNode = lepNONE;
|
sleNode = lpLedger->getDirNode(Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
||||||
sleNode = lpLedger->getDirNode(lspNode, Ledger::getDirNodeIndex(uRootIndex, uNodeDir));
|
|
||||||
|
|
||||||
assert(sleNode);
|
assert(sleNode);
|
||||||
}
|
}
|
||||||
} while (uNodeDir);
|
} while (uNodeDir);
|
||||||
@@ -1070,7 +1063,7 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
|||||||
|
|
||||||
std::string sql =
|
std::string sql =
|
||||||
str(boost::format("SELECT LedgerSeq,Status,RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions "
|
str(boost::format("SELECT LedgerSeq,Status,RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions "
|
||||||
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 1000) ORDER BY LedgerSeq;")
|
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 200) ORDER BY LedgerSeq DESC;")
|
||||||
% account.humanAccountID() % maxLedger % minLedger);
|
% account.humanAccountID() % maxLedger % minLedger);
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1092,7 +1085,7 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
|
|||||||
}else rawMeta.resize(metaSize);
|
}else rawMeta.resize(metaSize);
|
||||||
|
|
||||||
TransactionMetaSet::pointer meta= boost::make_shared<TransactionMetaSet>(txn->getID(), txn->getLedger(), rawMeta.getData());
|
TransactionMetaSet::pointer meta= boost::make_shared<TransactionMetaSet>(txn->getID(), txn->getLedger(), rawMeta.getData());
|
||||||
ret.push_back(std::pair<Transaction::ref, TransactionMetaSet::ref>(txn,meta));
|
ret.push_back(std::pair<Transaction::pointer, TransactionMetaSet::pointer>(txn,meta));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1212,7 +1205,16 @@ Json::Value NetworkOPs::getServerInfo(bool human, bool admin)
|
|||||||
static_cast<double>(Json::UInt(lpClosed->getReserve(0) * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
|
static_cast<double>(Json::UInt(lpClosed->getReserve(0) * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
|
||||||
l["reserve_inc_xrp"] =
|
l["reserve_inc_xrp"] =
|
||||||
static_cast<double>(Json::UInt(lpClosed->getReserveInc() * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
|
static_cast<double>(Json::UInt(lpClosed->getReserveInc() * baseFee / baseRef)) / SYSTEM_CURRENCY_PARTS;
|
||||||
l["age"] = Json::UInt(getCloseTimeNC() - lpClosed->getCloseTimeNC());
|
|
||||||
|
uint32 closeTime = getCloseTimeNC();
|
||||||
|
uint32 lCloseTime = lpClosed->getCloseTimeNC();
|
||||||
|
|
||||||
|
if (lCloseTime <= closeTime)
|
||||||
|
{
|
||||||
|
uint32 age = closeTime - lCloseTime;
|
||||||
|
if (age < 1000000)
|
||||||
|
l["age"] = Json::UInt(age);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
info["closed_ledger"] = l;
|
info["closed_ledger"] = l;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ public:
|
|||||||
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
||||||
|
|
||||||
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }
|
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }
|
||||||
|
SLE::pointer getSLEi(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLEi(uHash); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// Transaction operations
|
// Transaction operations
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ void OrderBookDB::setup(Ledger::ref ledger)
|
|||||||
|
|
||||||
while (currentIndex.isNonZero())
|
while (currentIndex.isNonZero())
|
||||||
{
|
{
|
||||||
SLE::pointer entry=ledger->getSLE(currentIndex);
|
SLE::pointer entry=ledger->getSLEi(currentIndex);
|
||||||
|
|
||||||
OrderBook::pointer book = OrderBook::newOrderBook(entry);
|
OrderBook::pointer book = OrderBook::newOrderBook(entry);
|
||||||
if (book)
|
if (book)
|
||||||
|
|||||||
@@ -24,11 +24,14 @@ DECLARE_INSTANCE(Peer);
|
|||||||
// Node has this long to verify its identity from connection accepted or connection attempt.
|
// Node has this long to verify its identity from connection accepted or connection attempt.
|
||||||
#define NODE_VERIFY_SECONDS 15
|
#define NODE_VERIFY_SECONDS 15
|
||||||
|
|
||||||
|
// Idle nodes are probed this often
|
||||||
|
#define NODE_IDLE_SECONDS 120
|
||||||
|
|
||||||
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx, uint64 peerID, bool inbound) :
|
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx, uint64 peerID, bool inbound) :
|
||||||
mInbound(inbound),
|
mInbound(inbound),
|
||||||
mHelloed(false),
|
mHelloed(false),
|
||||||
mDetaching(false),
|
mDetaching(false),
|
||||||
mActive(true),
|
mActive(2),
|
||||||
mCluster(false),
|
mCluster(false),
|
||||||
mPeerId(peerID),
|
mPeerId(peerID),
|
||||||
mSocketSsl(io_service, ctx),
|
mSocketSsl(io_service, ctx),
|
||||||
@@ -123,6 +126,33 @@ void Peer::detach(const char *rsn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Peer::handlePingTimer(const boost::system::error_code& ecResult)
|
||||||
|
{
|
||||||
|
if (ecResult || mDetaching)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mActive == 1)
|
||||||
|
{ // ping out
|
||||||
|
detach("pto");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mActive == 0)
|
||||||
|
{ // idle->pingsent
|
||||||
|
mActive = 1;
|
||||||
|
ripple::TMPing packet;
|
||||||
|
packet.set_type(ripple::TMPing::ptPING);
|
||||||
|
sendPacket(boost::make_shared<PackedMessage>(packet, ripple::mtPING));
|
||||||
|
}
|
||||||
|
else // active->idle
|
||||||
|
mActive = 0;
|
||||||
|
|
||||||
|
mActivityTimer.expires_from_now(boost::posix_time::seconds(NODE_IDLE_SECONDS));
|
||||||
|
mActivityTimer.async_wait(boost::bind(&Peer::handlePingTimer, shared_from_this(),
|
||||||
|
boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
|
void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
|
||||||
{
|
{
|
||||||
if (ecResult == boost::asio::error::operation_aborted)
|
if (ecResult == boost::asio::error::operation_aborted)
|
||||||
@@ -631,8 +661,10 @@ void Peer::recvHello(ripple::TMHello& packet)
|
|||||||
{
|
{
|
||||||
bool bDetach = true;
|
bool bDetach = true;
|
||||||
|
|
||||||
// Cancel verification timeout. - FIXME Start ping/pong timer
|
|
||||||
(void) mActivityTimer.cancel();
|
(void) mActivityTimer.cancel();
|
||||||
|
mActivityTimer.expires_from_now(boost::posix_time::seconds(NODE_IDLE_SECONDS));
|
||||||
|
mActivityTimer.async_wait(boost::bind(&Peer::handlePingTimer, shared_from_this(),
|
||||||
|
boost::asio::placeholders::error));
|
||||||
|
|
||||||
uint32 ourTime = theApp->getOPs().getNetworkTimeNC();
|
uint32 ourTime = theApp->getOPs().getNetworkTimeNC();
|
||||||
uint32 minTime = ourTime - 20;
|
uint32 minTime = ourTime - 20;
|
||||||
@@ -1197,7 +1229,7 @@ void Peer::recvPing(ripple::TMPing& packet)
|
|||||||
}
|
}
|
||||||
else if (packet.type() == ripple::TMPing::ptPONG)
|
else if (packet.type() == ripple::TMPing::ptPONG)
|
||||||
{
|
{
|
||||||
mActive = true;
|
mActive = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ private:
|
|||||||
bool mClientConnect; // In process of connecting as client.
|
bool mClientConnect; // In process of connecting as client.
|
||||||
bool mHelloed; // True, if hello accepted.
|
bool mHelloed; // True, if hello accepted.
|
||||||
bool mDetaching; // True, if detaching.
|
bool mDetaching; // True, if detaching.
|
||||||
bool mActive;
|
int mActive; // 0=idle, 1=pingsent, 2=active
|
||||||
bool mCluster; // Node in our cluster
|
bool mCluster; // Node in our cluster
|
||||||
RippleAddress mNodePublic; // Node public key of peer.
|
RippleAddress mNodePublic; // Node public key of peer.
|
||||||
std::string mNodeName;
|
std::string mNodeName;
|
||||||
@@ -58,6 +58,7 @@ private:
|
|||||||
|
|
||||||
void handleStart(const boost::system::error_code& ecResult);
|
void handleStart(const boost::system::error_code& ecResult);
|
||||||
void handleVerifyTimer(const boost::system::error_code& ecResult);
|
void handleVerifyTimer(const boost::system::error_code& ecResult);
|
||||||
|
void handlePingTimer(const boost::system::error_code& ecResult);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ Json::Value RPCHandler::transactionSign(Json::Value jvRequest, bool bSubmit)
|
|||||||
if (!txJSON.isMember("Flags")) txJSON["Flags"] = 0;
|
if (!txJSON.isMember("Flags")) txJSON["Flags"] = 0;
|
||||||
|
|
||||||
Ledger::pointer lpCurrent = mNetOps->getCurrentLedger();
|
Ledger::pointer lpCurrent = mNetOps->getCurrentLedger();
|
||||||
SLE::pointer sleAccountRoot = mNetOps->getSLE(lpCurrent, Ledger::getAccountRootIndex(raSrcAddressID.getAccountID()));
|
SLE::pointer sleAccountRoot = mNetOps->getSLEi(lpCurrent, Ledger::getAccountRootIndex(raSrcAddressID.getAccountID()));
|
||||||
|
|
||||||
if (!sleAccountRoot)
|
if (!sleAccountRoot)
|
||||||
{
|
{
|
||||||
@@ -899,7 +899,7 @@ Json::Value RPCHandler::doAccountLines(Json::Value jvRequest)
|
|||||||
if (!lpLedger)
|
if (!lpLedger)
|
||||||
return jvResult;
|
return jvResult;
|
||||||
|
|
||||||
ScopedUnlock su(theApp->getMasterLock(), lpLedger->isFixed());
|
ScopedUnlock su(theApp->getMasterLock());
|
||||||
|
|
||||||
if (!jvRequest.isMember("account"))
|
if (!jvRequest.isMember("account"))
|
||||||
return rpcError(rpcINVALID_PARAMS);
|
return rpcError(rpcINVALID_PARAMS);
|
||||||
@@ -980,7 +980,7 @@ Json::Value RPCHandler::doAccountOffers(Json::Value jvRequest)
|
|||||||
if (!lpLedger)
|
if (!lpLedger)
|
||||||
return jvResult;
|
return jvResult;
|
||||||
|
|
||||||
ScopedUnlock su(theApp->getMasterLock(), lpLedger->isClosed() || lpLedger->isImmutable());
|
ScopedUnlock su(theApp->getMasterLock());
|
||||||
|
|
||||||
if (!jvRequest.isMember("account"))
|
if (!jvRequest.isMember("account"))
|
||||||
return rpcError(rpcINVALID_PARAMS);
|
return rpcError(rpcINVALID_PARAMS);
|
||||||
@@ -1526,6 +1526,7 @@ Json::Value RPCHandler::doLedger(Json::Value jvRequest)
|
|||||||
|
|
||||||
Json::Value ret(Json::objectValue);
|
Json::Value ret(Json::objectValue);
|
||||||
|
|
||||||
|
ScopedUnlock(theApp->getMasterLock());
|
||||||
ledger->addJson(ret, full ? LEDGER_JSON_FULL : 0);
|
ledger->addJson(ret, full ? LEDGER_JSON_FULL : 0);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2147,7 +2148,7 @@ Json::Value RPCHandler::lookupLedger(Json::Value jvRequest, Ledger::pointer& lpL
|
|||||||
if (-3 == iLedgerIndex)
|
if (-3 == iLedgerIndex)
|
||||||
{ // Last fully-validated ledger
|
{ // Last fully-validated ledger
|
||||||
lpLedger = mNetOps->getValidatedLedger();
|
lpLedger = mNetOps->getValidatedLedger();
|
||||||
iLedgerIndex = lpLedger->getLedgerSeq();
|
iLedgerIndex = lpLedger->getLedgerSeq();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iLedgerIndex <= 0)
|
if (iLedgerIndex <= 0)
|
||||||
@@ -2364,7 +2365,7 @@ Json::Value RPCHandler::doLedgerEntry(Json::Value jvRequest)
|
|||||||
|
|
||||||
if (!!uNodeIndex)
|
if (!!uNodeIndex)
|
||||||
{
|
{
|
||||||
SLE::pointer sleNode = mNetOps->getSLE(lpLedger, uNodeIndex);
|
SLE::pointer sleNode = mNetOps->getSLEi(lpLedger, uNodeIndex);
|
||||||
|
|
||||||
if (!sleNode)
|
if (!sleNode)
|
||||||
{
|
{
|
||||||
@@ -2833,7 +2834,8 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
|
|||||||
return rpcError(rpcNO_PERMISSION);
|
return rpcError(rpcNO_PERMISSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Need the master lock for getOperatingMode
|
boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
|
||||||
|
|
||||||
if (commandsA[i].iOptions & optNetwork
|
if (commandsA[i].iOptions & optNetwork
|
||||||
&& mNetOps->getOperatingMode() != NetworkOPs::omTRACKING
|
&& mNetOps->getOperatingMode() != NetworkOPs::omTRACKING
|
||||||
&& mNetOps->getOperatingMode() != NetworkOPs::omFULL)
|
&& mNetOps->getOperatingMode() != NetworkOPs::omFULL)
|
||||||
@@ -2842,7 +2844,6 @@ Json::Value RPCHandler::doCommand(const Json::Value& jvRequest, int iRole)
|
|||||||
}
|
}
|
||||||
// XXX Should verify we have a current ledger.
|
// XXX Should verify we have a current ledger.
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl(theApp->getMasterLock());
|
|
||||||
if ((commandsA[i].iOptions & optCurrent) && false)
|
if ((commandsA[i].iOptions & optCurrent) && false)
|
||||||
{
|
{
|
||||||
return rpcError(rpcNO_CURRENT);
|
return rpcError(rpcNO_CURRENT);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/functional/hash.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
@@ -293,6 +295,9 @@ uint160 RippleAddress::getAccountID() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boost::mutex rncLock;
|
||||||
|
static boost::unordered_map< std::vector<unsigned char>, std::string > rncMap;
|
||||||
|
|
||||||
std::string RippleAddress::humanAccountID() const
|
std::string RippleAddress::humanAccountID() const
|
||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
@@ -300,7 +305,13 @@ std::string RippleAddress::humanAccountID() const
|
|||||||
throw std::runtime_error("unset source - humanAccountID");
|
throw std::runtime_error("unset source - humanAccountID");
|
||||||
|
|
||||||
case VER_ACCOUNT_ID:
|
case VER_ACCOUNT_ID:
|
||||||
return ToString();
|
{
|
||||||
|
boost::mutex::scoped_lock sl(rncLock);
|
||||||
|
boost::unordered_map< std::vector<unsigned char>, std::string >::iterator it = rncMap.find(vchData);
|
||||||
|
if (it != rncMap.end())
|
||||||
|
return it->second;
|
||||||
|
return rncMap[vchData] = ToString();
|
||||||
|
}
|
||||||
|
|
||||||
case VER_ACCOUNT_PUBLIC:
|
case VER_ACCOUNT_PUBLIC:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -485,6 +485,17 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id, SHAMapTreeNode::TNType&
|
|||||||
return leaf->peekItem();
|
return leaf->peekItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHAMapItem::pointer SHAMap::peekItem(const uint256& id, uint256& hash)
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
SHAMapTreeNode* leaf = walkToPointer(id);
|
||||||
|
if (!leaf)
|
||||||
|
return no_item;
|
||||||
|
hash = leaf->getNodeHash();
|
||||||
|
return leaf->peekItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SHAMap::hasItem(const uint256& id)
|
bool SHAMap::hasItem(const uint256& id)
|
||||||
{ // does the tree have an item with this ID
|
{ // does the tree have an item with this ID
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
|||||||
@@ -406,6 +406,7 @@ public:
|
|||||||
|
|
||||||
// save a copy if you only need a temporary
|
// save a copy if you only need a temporary
|
||||||
SHAMapItem::pointer peekItem(const uint256& id);
|
SHAMapItem::pointer peekItem(const uint256& id);
|
||||||
|
SHAMapItem::pointer peekItem(const uint256& id, uint256& hash);
|
||||||
SHAMapItem::pointer peekItem(const uint256& id, SHAMapTreeNode::TNType& type);
|
SHAMapItem::pointer peekItem(const uint256& id, SHAMapTreeNode::TNType& type);
|
||||||
|
|
||||||
// traverse functions
|
// traverse functions
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ DECLARE_INSTANCE(SerializedLedgerEntry)
|
|||||||
SETUP_LOG();
|
SETUP_LOG();
|
||||||
|
|
||||||
SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index)
|
SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index)
|
||||||
: STObject(sfLedgerEntry), mIndex(index)
|
: STObject(sfLedgerEntry), mIndex(index), mMutable(true)
|
||||||
{
|
{
|
||||||
set(sit);
|
set(sit);
|
||||||
uint16 type = getFieldU16(sfLedgerEntryType);
|
uint16 type = getFieldU16(sfLedgerEntryType);
|
||||||
@@ -22,7 +22,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& index)
|
SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& index)
|
||||||
: STObject(sfLedgerEntry), mIndex(index)
|
: STObject(sfLedgerEntry), mIndex(index), mMutable(true)
|
||||||
{
|
{
|
||||||
SerializerIterator sit(const_cast<Serializer&>(s)); // we know 's' isn't going away
|
SerializerIterator sit(const_cast<Serializer&>(s)); // we know 's' isn't going away
|
||||||
set(sit);
|
set(sit);
|
||||||
@@ -41,7 +41,7 @@ SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256&
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256& index) :
|
SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256& index) :
|
||||||
STObject(sfLedgerEntry), mIndex(index), mType(type)
|
STObject(sfLedgerEntry), mIndex(index), mType(type), mMutable(true)
|
||||||
{
|
{
|
||||||
mFormat = LedgerEntryFormat::getLgrFormat(type);
|
mFormat = LedgerEntryFormat::getLgrFormat(type);
|
||||||
if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type");
|
if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type");
|
||||||
@@ -49,6 +49,13 @@ SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type, const uint256
|
|||||||
setFieldU16(sfLedgerEntryType, static_cast<uint16>(mFormat->t_type));
|
setFieldU16(sfLedgerEntryType, static_cast<uint16>(mFormat->t_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SerializedLedgerEntry::pointer SerializedLedgerEntry::getMutable() const
|
||||||
|
{
|
||||||
|
SerializedLedgerEntry::pointer ret = boost::make_shared<SerializedLedgerEntry>(boost::ref(*this));
|
||||||
|
ret->mMutable = true;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
std::string SerializedLedgerEntry::getFullText() const
|
std::string SerializedLedgerEntry::getFullText() const
|
||||||
{
|
{
|
||||||
std::string ret = "\"";
|
std::string ret = "\"";
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ protected:
|
|||||||
uint256 mIndex;
|
uint256 mIndex;
|
||||||
LedgerEntryType mType;
|
LedgerEntryType mType;
|
||||||
const LedgerEntryFormat* mFormat;
|
const LedgerEntryFormat* mFormat;
|
||||||
|
bool mMutable;
|
||||||
|
|
||||||
SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); }
|
SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); }
|
||||||
|
|
||||||
@@ -34,6 +35,10 @@ public:
|
|||||||
const uint256& getIndex() const { return mIndex; }
|
const uint256& getIndex() const { return mIndex; }
|
||||||
void setIndex(const uint256& i) { mIndex = i; }
|
void setIndex(const uint256& i) { mIndex = i; }
|
||||||
|
|
||||||
|
void setImmutable() { mMutable = false; }
|
||||||
|
bool isMutable() { return mMutable; }
|
||||||
|
SerializedLedgerEntry::pointer getMutable() const;
|
||||||
|
|
||||||
LedgerEntryType getType() const { return mType; }
|
LedgerEntryType getType() const { return mType; }
|
||||||
uint16 getVersion() const { return getFieldU16(sfLedgerEntryType); }
|
uint16 getVersion() const { return getFieldU16(sfLedgerEntryType); }
|
||||||
const LedgerEntryFormat* getFormat() { return mFormat; }
|
const LedgerEntryFormat* getFormat() { return mFormat; }
|
||||||
|
|||||||
@@ -147,16 +147,18 @@ void STObject::set(const std::vector<SOElement::ref>& type)
|
|||||||
|
|
||||||
bool STObject::setType(const std::vector<SOElement::ref> &type)
|
bool STObject::setType(const std::vector<SOElement::ref> &type)
|
||||||
{
|
{
|
||||||
boost::ptr_vector<SerializedType> newData;
|
boost::ptr_vector<SerializedType> newData(type.size());
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
|
|
||||||
mType.clear();
|
mType.clear();
|
||||||
|
mType.reserve(type.size());
|
||||||
|
|
||||||
BOOST_FOREACH(SOElement::ref elem, type)
|
BOOST_FOREACH(SOElement::ref elem, type)
|
||||||
{
|
{
|
||||||
bool match = false;
|
bool match = false;
|
||||||
for (boost::ptr_vector<SerializedType>::iterator it = mData.begin(); it != mData.end(); ++it)
|
for (boost::ptr_vector<SerializedType>::iterator it = mData.begin(); it != mData.end(); ++it)
|
||||||
if (it->getFName() == elem->e_field)
|
if (it->getFName() == elem->e_field)
|
||||||
{
|
{ // matching entry, move to new vector
|
||||||
match = true;
|
match = true;
|
||||||
newData.push_back(mData.release(it).release());
|
newData.push_back(mData.release(it).release());
|
||||||
if ((elem->flags == SOE_DEFAULT) && it->isDefault())
|
if ((elem->flags == SOE_DEFAULT) && it->isDefault())
|
||||||
@@ -169,7 +171,7 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!match)
|
if (!match)
|
||||||
{
|
{ // no match found
|
||||||
if (elem->flags == SOE_REQUIRED)
|
if (elem->flags == SOE_REQUIRED)
|
||||||
{
|
{
|
||||||
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid missing "
|
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid missing "
|
||||||
@@ -181,18 +183,17 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
|
|||||||
|
|
||||||
mType.push_back(elem);
|
mType.push_back(elem);
|
||||||
}
|
}
|
||||||
if (mData.size() != 0)
|
|
||||||
{
|
BOOST_FOREACH(const SerializedType& t, mData)
|
||||||
BOOST_FOREACH(const SerializedType& t, mData)
|
{ // Anything left over must be discardable
|
||||||
|
if (!t.getFName().isDiscardable())
|
||||||
{
|
{
|
||||||
if (!t.getFName().isDiscardable())
|
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid leftover "
|
||||||
{
|
<< t.getFName().getName();
|
||||||
cLog(lsWARNING) << "setType( " << getFName().getName() << ") invalid leftover "
|
valid = false;
|
||||||
<< t.getFName().getName();
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mData.swap(newData);
|
mData.swap(newData);
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,22 +282,23 @@ STAccount* STAccount::construct(SerializerIterator& u, SField::ref name)
|
|||||||
STVector256* STVector256::construct(SerializerIterator& u, SField::ref name)
|
STVector256* STVector256::construct(SerializerIterator& u, SField::ref name)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> data = u.getVL();
|
std::vector<unsigned char> data = u.getVL();
|
||||||
std::vector<uint256> value;
|
|
||||||
|
std::auto_ptr<STVector256> vec(new STVector256(name));
|
||||||
|
|
||||||
int count = data.size() / (256 / 8);
|
int count = data.size() / (256 / 8);
|
||||||
value.reserve(count);
|
vec->mValue.reserve(count);
|
||||||
|
|
||||||
unsigned int uStart = 0;
|
unsigned int uStart = 0;
|
||||||
for (unsigned int i = 0; i != count; i++)
|
for (unsigned int i = 0; i != count; i++)
|
||||||
{
|
{
|
||||||
unsigned int uEnd = uStart+(256/8);
|
unsigned int uEnd = uStart+(256/8);
|
||||||
|
|
||||||
value.push_back(uint256(std::vector<unsigned char>(data.begin()+uStart, data.begin()+(uStart+32))));
|
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
|
||||||
|
vec->mValue.push_back(uint256(std::vector<unsigned char>(data.begin()+uStart, data.begin()+uEnd)));
|
||||||
uStart = uEnd;
|
uStart = uEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new STVector256(name, value);
|
return vec.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void STVector256::add(Serializer& s) const
|
void STVector256::add(Serializer& s) const
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "../json/value.h"
|
#include "../json/value.h"
|
||||||
|
|
||||||
#include <boost/weak_ptr.hpp>
|
#include <boost/weak_ptr.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
#include "WSDoor.h"
|
#include "WSDoor.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
@@ -17,7 +18,7 @@
|
|||||||
DEFINE_INSTANCE(WebSocketConnection);
|
DEFINE_INSTANCE(WebSocketConnection);
|
||||||
|
|
||||||
#ifndef WEBSOCKET_PING_FREQUENCY
|
#ifndef WEBSOCKET_PING_FREQUENCY
|
||||||
#define WEBSOCKET_PING_FREQUENCY 120
|
#define WEBSOCKET_PING_FREQUENCY (5*60)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename endpoint_type>
|
template <typename endpoint_type>
|
||||||
@@ -53,7 +54,7 @@ public:
|
|||||||
|
|
||||||
WSConnection(WSServerHandler<endpoint_type>* wshpHandler, const connection_ptr& cpConnection)
|
WSConnection(WSServerHandler<endpoint_type>* wshpHandler, const connection_ptr& cpConnection)
|
||||||
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()),
|
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()),
|
||||||
mPingTimer(theApp->getAuxService()), mPinged(false)
|
mPingTimer(cpConnection->get_io_service()), mPinged(false)
|
||||||
{
|
{
|
||||||
mRemoteIP = cpConnection->get_socket().lowest_layer().remote_endpoint().address().to_string();
|
mRemoteIP = cpConnection->get_socket().lowest_layer().remote_endpoint().address().to_string();
|
||||||
cLog(lsDEBUG) << "Websocket connection from " << mRemoteIP;
|
cLog(lsDEBUG) << "Websocket connection from " << mRemoteIP;
|
||||||
@@ -62,6 +63,7 @@ public:
|
|||||||
|
|
||||||
void preDestroy()
|
void preDestroy()
|
||||||
{ // sever connection
|
{ // sever connection
|
||||||
|
mPingTimer.cancel();
|
||||||
mConnection.reset();
|
mConnection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,10 +145,10 @@ public:
|
|||||||
bool onPingTimer()
|
bool onPingTimer()
|
||||||
{
|
{
|
||||||
if (mPinged)
|
if (mPinged)
|
||||||
return true;
|
return true; // causes connection to close
|
||||||
mPinged = true;
|
mPinged = true;
|
||||||
setPingTimer();
|
setPingTimer();
|
||||||
return false;
|
return false; // causes ping to be sent
|
||||||
}
|
}
|
||||||
|
|
||||||
void onPong()
|
void onPong()
|
||||||
@@ -154,8 +156,11 @@ public:
|
|||||||
mPinged = false;
|
mPinged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pingTimer(weak_connection_ptr c, WSServerHandler<endpoint_type>* h)
|
static void pingTimer(weak_connection_ptr c, WSServerHandler<endpoint_type>* h, const boost::system::error_code& e)
|
||||||
{
|
{
|
||||||
|
if (e)
|
||||||
|
return;
|
||||||
|
|
||||||
connection_ptr ptr = c.lock();
|
connection_ptr ptr = c.lock();
|
||||||
if (ptr)
|
if (ptr)
|
||||||
h->pingTimer(ptr);
|
h->pingTimer(ptr);
|
||||||
@@ -164,10 +169,10 @@ public:
|
|||||||
void setPingTimer()
|
void setPingTimer()
|
||||||
{
|
{
|
||||||
mPingTimer.expires_from_now(boost::posix_time::seconds(WEBSOCKET_PING_FREQUENCY));
|
mPingTimer.expires_from_now(boost::posix_time::seconds(WEBSOCKET_PING_FREQUENCY));
|
||||||
mPingTimer.async_wait(boost::bind(&WSConnection<endpoint_type>::pingTimer, mConnection, mHandler));
|
mPingTimer.async_wait(boost::bind(
|
||||||
|
&WSConnection<endpoint_type>::pingTimer, mConnection, mHandler, boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// vim:ts=4
|
// vim:ts=4
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ protected:
|
|||||||
memset(&vchData[0], 0, vchData.size());
|
memset(&vchData[0], 0, vchData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetData(int nVersionIn, std::vector<unsigned char> vchDataIn)
|
void SetData(int nVersionIn, const std::vector<unsigned char>& vchDataIn)
|
||||||
{
|
{
|
||||||
nVersion = nVersionIn;
|
nVersion = nVersionIn;
|
||||||
vchData = vchDataIn;
|
vchData = vchDataIn;
|
||||||
@@ -186,7 +186,7 @@ protected:
|
|||||||
{
|
{
|
||||||
nVersion = nVersionIn;
|
nVersion = nVersionIn;
|
||||||
vchData.resize(nSize);
|
vchData.resize(nSize);
|
||||||
if (!vchData.empty())
|
if (nSize)
|
||||||
memcpy(&vchData[0], pdata, nSize);
|
memcpy(&vchData[0], pdata, nSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
src/js/orderbook.js
Normal file
104
src/js/orderbook.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
// Routines for working with an orderbook.
|
||||||
|
//
|
||||||
|
// Events:
|
||||||
|
|
||||||
|
// var network = require("./network.js");
|
||||||
|
|
||||||
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
var Amount = require('./amount').Amount;
|
||||||
|
var UInt160 = require('./uint160').UInt160;
|
||||||
|
var Currency = require('./currency').Currency;
|
||||||
|
|
||||||
|
var extend = require('extend');
|
||||||
|
|
||||||
|
var OrderBook = function (remote,
|
||||||
|
currency_out, issuer_out,
|
||||||
|
currency_in, issuer_in) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this._remote = remote;
|
||||||
|
this._currency_out = currency_out;
|
||||||
|
this._issuer_out = issuer_out;
|
||||||
|
this._currency_in = currency_in;
|
||||||
|
this._issuer_in = issuer_in;
|
||||||
|
|
||||||
|
this._subs = 0;
|
||||||
|
|
||||||
|
// Ledger entry object
|
||||||
|
// Important: This must never be overwritten, only extend()-ed
|
||||||
|
this._entry = {};
|
||||||
|
|
||||||
|
this.on('newListener', function (type, listener) {
|
||||||
|
if (OrderBook.subscribe_events.indexOf(type) !== -1) {
|
||||||
|
if (!self._subs && 'open' === self._remote._online_state) {
|
||||||
|
self._remote.request_subscribe()
|
||||||
|
.books([self.to_json()])
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
self._subs += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on('removeListener', function (type, listener) {
|
||||||
|
if (OrderBook.subscribe_events.indexOf(type) !== -1) {
|
||||||
|
self._subs -= 1;
|
||||||
|
|
||||||
|
if (!self._subs && 'open' === self._remote._online_state) {
|
||||||
|
self._remote.request_unsubscribe()
|
||||||
|
.books([self.to_json()])
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._remote.on('connect', function () {
|
||||||
|
if (self._subs) {
|
||||||
|
self._remote.request_subscribe()
|
||||||
|
.books([self.to_json()])
|
||||||
|
.request();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
OrderBook.prototype = new EventEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of events that require a remote subscription to the orderbook.
|
||||||
|
*/
|
||||||
|
OrderBook.subscribe_events = ['transaction'];
|
||||||
|
|
||||||
|
OrderBook.prototype.to_json = function ()
|
||||||
|
{
|
||||||
|
var json = {
|
||||||
|
"CurrencyOut": this._currency_out,
|
||||||
|
"CurrencyIn": this._currency_in
|
||||||
|
};
|
||||||
|
|
||||||
|
if (json["CurrencyOut"] !== "XRP") json["IssuerOut"] = this._issuer_out;
|
||||||
|
if (json["CurrencyIn"] !== "XRP") json["IssuerIn"] = this._issuer_in;
|
||||||
|
|
||||||
|
return json;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the OrderBook is valid.
|
||||||
|
*
|
||||||
|
* Note: This only checks whether the parameters (currencies and issuer) are
|
||||||
|
* syntactically valid. It does not check anything against the ledger.
|
||||||
|
*/
|
||||||
|
OrderBook.prototype.is_valid = function ()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
Currency.is_valid(this._currency_in) &&
|
||||||
|
(this._currency_in !== "XRP" && UInt160.is_valid(this._issuer_in)) &&
|
||||||
|
Currency.is_valid(this._currency_out) &&
|
||||||
|
(this._currency_out !== "XRP" && UInt160.is_valid(this._issuer_out)) &&
|
||||||
|
!(this._currency_in === "XRP" && this._currency_out === "XRP")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.OrderBook = OrderBook;
|
||||||
|
|
||||||
|
// vim:sw=2:sts=2:ts=8:et
|
||||||
@@ -22,6 +22,7 @@ var UInt160 = require('./amount').UInt160;
|
|||||||
var Transaction = require('./transaction').Transaction;
|
var Transaction = require('./transaction').Transaction;
|
||||||
var Account = require('./account').Account;
|
var Account = require('./account').Account;
|
||||||
var Meta = require('./meta').Meta;
|
var Meta = require('./meta').Meta;
|
||||||
|
var OrderBook = require('./orderbook').OrderBook;
|
||||||
|
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var config = require('./config');
|
var config = require('./config');
|
||||||
@@ -181,6 +182,31 @@ Request.prototype.rt_accounts = function (accounts) {
|
|||||||
return this.accounts(accounts, true);
|
return this.accounts(accounts, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Request.prototype.books = function (books) {
|
||||||
|
var procBooks = [];
|
||||||
|
|
||||||
|
for (var i = 0, l = books.length; i < l; i++) {
|
||||||
|
var book = books[i];
|
||||||
|
|
||||||
|
var json = {
|
||||||
|
"CurrencyOut": Currency.json_rewrite(book["CurrencyOut"]),
|
||||||
|
"CurrencyIn": Currency.json_rewrite(book["CurrencyIn"])
|
||||||
|
};
|
||||||
|
|
||||||
|
if (json["CurrencyOut"] !== "XRP") {
|
||||||
|
json["IssuerOut"] = UInt160.json_rewrite(book["IssuerOut"]);
|
||||||
|
}
|
||||||
|
if (json["CurrencyIn"] !== "XRP") {
|
||||||
|
json["IssuerIn"] = UInt160.json_rewrite(book["IssuerIn"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
procBooks.push(json);
|
||||||
|
}
|
||||||
|
this.message.books = procBooks;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Remote - access to a remote Ripple server via websocket.
|
// Remote - access to a remote Ripple server via websocket.
|
||||||
//
|
//
|
||||||
@@ -1036,6 +1062,15 @@ Remote.prototype.account = function (accountId) {
|
|||||||
return this._accounts[account.to_json()] = account;
|
return this._accounts[account.to_json()] = account;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Remote.prototype.book = function (currency_out, issuer_out,
|
||||||
|
currency_in, issuer_in) {
|
||||||
|
var book = new OrderBook(this,
|
||||||
|
currency_out, issuer_out,
|
||||||
|
currency_in, issuer_in);
|
||||||
|
|
||||||
|
return book;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the next account sequence if possible.
|
// Return the next account sequence if possible.
|
||||||
// <-- undefined or Sequence
|
// <-- undefined or Sequence
|
||||||
Remote.prototype.account_seq = function (account, advance) {
|
Remote.prototype.account_seq = function (account, advance) {
|
||||||
|
|||||||
@@ -218,6 +218,11 @@ buster.testCase("Amount", {
|
|||||||
"Divide EUR by XRP, neg, <1" : function () {
|
"Divide EUR by XRP, neg, <1" : function () {
|
||||||
buster.assert.equals("-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000")).to_text_full());
|
buster.assert.equals("-0.05/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", Amount.from_json("-100/EUR/rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh").divide(Amount.from_json("2000")).to_text_full());
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Amount comparisons" : {
|
||||||
|
"10 USD != 100 USD" : function () {
|
||||||
|
buster.refute(Amount.from_json("10/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL").equals(Amount.from_json("100/USD/rNDKeo9RrCiRdfsMG8AdoZvNZxHASGzbZL")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user