mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of https://github.com/jedmccaleb/NewCoin
This commit is contained in:
@@ -171,6 +171,7 @@
|
||||
<ClCompile Include="src\utils.cpp" />
|
||||
<ClCompile Include="src\ValidationCollection.cpp" />
|
||||
<ClCompile Include="src\Wallet.cpp" />
|
||||
<ClCompile Include="src\WSConnection.cpp" />
|
||||
<ClCompile Include="src\WSDoor.cpp" />
|
||||
<ClCompile Include="websocketpp\src\base64\base64.cpp" />
|
||||
<ClCompile Include="websocketpp\src\md5\md5.c" />
|
||||
@@ -205,15 +206,20 @@
|
||||
<ClInclude Include="src\ConnectionPool.h" />
|
||||
<ClInclude Include="src\Contract.h" />
|
||||
<ClInclude Include="src\Conversion.h" />
|
||||
<ClInclude Include="src\FieldNames.h" />
|
||||
<ClInclude Include="src\HashedObject.h" />
|
||||
<ClInclude Include="src\HashPrefixes.h" />
|
||||
<ClInclude Include="src\HttpReply.h" />
|
||||
<ClInclude Include="src\HttpRequest.h" />
|
||||
<ClInclude Include="src\HttpsClient.h" />
|
||||
<ClInclude Include="src\InstanceCounter.h" />
|
||||
<ClInclude Include="src\Interpreter.h" />
|
||||
<ClInclude Include="src\JobQueue.h" />
|
||||
<ClInclude Include="src\key.h" />
|
||||
<ClInclude Include="src\Ledger.h" />
|
||||
<ClInclude Include="src\LedgerAcquire.h" />
|
||||
<ClInclude Include="src\LedgerConsensus.h" />
|
||||
<ClInclude Include="src\LedgerEntrySet.h" />
|
||||
<ClInclude Include="src\LedgerFormats.h" />
|
||||
<ClInclude Include="src\LedgerHistory.h" />
|
||||
<ClInclude Include="src\LedgerMaster.h" />
|
||||
@@ -233,8 +239,12 @@
|
||||
<ClInclude Include="src\Peer.h" />
|
||||
<ClInclude Include="src\PeerDoor.h" />
|
||||
<ClInclude Include="src\PubKeyCache.h" />
|
||||
<ClInclude Include="src\RangeSet.h" />
|
||||
<ClInclude Include="src\RequestParser.h" />
|
||||
<ClInclude Include="src\rfc1751.h" />
|
||||
<ClInclude Include="src\ripple.pb.h" />
|
||||
<ClInclude Include="src\RippleAddress.h" />
|
||||
<ClInclude Include="src\RippleCalc.h" />
|
||||
<ClInclude Include="src\RippleLines.h" />
|
||||
<ClInclude Include="src\RippleState.h" />
|
||||
<ClInclude Include="src\RPC.h" />
|
||||
@@ -250,19 +260,29 @@
|
||||
<ClInclude Include="src\SerializedTransaction.h" />
|
||||
<ClInclude Include="src\SerializedTypes.h" />
|
||||
<ClInclude Include="src\SerializedValidation.h" />
|
||||
<ClInclude Include="src\SerializeProto.h" />
|
||||
<ClInclude Include="src\Serializer.h" />
|
||||
<ClInclude Include="src\SHAMap.h" />
|
||||
<ClInclude Include="src\SHAMapSync.h" />
|
||||
<ClInclude Include="src\SNTPClient.h" />
|
||||
<ClInclude Include="src\Suppression.h" />
|
||||
<ClInclude Include="src\TaggedCache.h" />
|
||||
<ClInclude Include="src\Transaction.h" />
|
||||
<ClInclude Include="src\TransactionEngine.h" />
|
||||
<ClInclude Include="src\TransactionErr.h" />
|
||||
<ClInclude Include="src\TransactionFormats.h" />
|
||||
<ClInclude Include="src\TransactionMaster.h" />
|
||||
<ClInclude Include="src\TransactionMeta.h" />
|
||||
<ClInclude Include="src\types.h" />
|
||||
<ClInclude Include="src\uint256.h" />
|
||||
<ClInclude Include="src\UniqueNodeList.h" />
|
||||
<ClInclude Include="src\utils.h" />
|
||||
<ClInclude Include="src\ValidationCollection.h" />
|
||||
<ClInclude Include="src\Version.h" />
|
||||
<ClInclude Include="src\Wallet.h" />
|
||||
<ClInclude Include="src\WSConnection.h" />
|
||||
<ClInclude Include="src\WSDoor.h" />
|
||||
<ClInclude Include="src\WSHandler.h" />
|
||||
<ClInclude Include="TimingService.h" />
|
||||
<ClInclude Include="ExtendedTransaction.h" />
|
||||
<ClInclude Include="util\pugiconfig.hpp" />
|
||||
|
||||
@@ -309,6 +309,15 @@
|
||||
<ClCompile Include="src\RangeSet.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\JobQueue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\InstanceCounter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\WSConnection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="KnownNodeList.h">
|
||||
@@ -566,6 +575,63 @@
|
||||
<ClInclude Include="src\RPCHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\WSHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\FieldNames.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\HashPrefixes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\InstanceCounter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\JobQueue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\LedgerEntrySet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\RangeSet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ripple.pb.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\RippleAddress.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\RippleCalc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SerializeProto.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SHAMapSync.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\SNTPClient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Suppression.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\TransactionErr.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\TransactionMeta.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\WSConnection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\WSDoor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="wallet.xml" />
|
||||
|
||||
@@ -16,7 +16,7 @@ SETUP_LOG();
|
||||
|
||||
uint64 STAmount::uRateOne = STAmount::getRate(STAmount(1), STAmount(1));
|
||||
|
||||
// --> sCurrency: "", "XNS", or three letter ISO code.
|
||||
// --> sCurrency: "", "XRP", or three letter ISO code.
|
||||
bool STAmount::currencyFromString(uint160& uDstCurrency, const std::string& sCurrency)
|
||||
{
|
||||
bool bSuccess = true;
|
||||
@@ -1365,19 +1365,19 @@ BOOST_AUTO_TEST_CASE( CustomCurrency_test )
|
||||
|
||||
if (STAmount::multiply(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 20), STAmount(3), CURRENCY_ONE, ACCOUNT_ONE).getText() != "60")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
if (STAmount::multiply(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 20), STAmount(3), uint160(), ACCOUNT_XNS).getText() != "60")
|
||||
if (STAmount::multiply(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 20), STAmount(3), uint160(), ACCOUNT_XRP).getText() != "60")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
if (STAmount::multiply(STAmount(20), STAmount(3), CURRENCY_ONE, ACCOUNT_ONE).getText() != "60")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
if (STAmount::multiply(STAmount(20), STAmount(3), uint160(), ACCOUNT_XNS).getText() != "60")
|
||||
if (STAmount::multiply(STAmount(20), STAmount(3), uint160(), ACCOUNT_XRP).getText() != "60")
|
||||
BOOST_FAIL("STAmount multiply fail");
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(3), CURRENCY_ONE, ACCOUNT_ONE).getText() != "20")
|
||||
BOOST_FAIL("STAmount divide fail");
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(3), uint160(), ACCOUNT_XNS).getText() != "20")
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(3), uint160(), ACCOUNT_XRP).getText() != "20")
|
||||
BOOST_FAIL("STAmount divide fail");
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(CURRENCY_ONE, ACCOUNT_ONE, 3), CURRENCY_ONE, ACCOUNT_ONE).getText() != "20")
|
||||
BOOST_FAIL("STAmount divide fail");
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(CURRENCY_ONE, ACCOUNT_ONE, 3), uint160(), ACCOUNT_XNS).getText() != "20")
|
||||
if (STAmount::divide(STAmount(CURRENCY_ONE, ACCOUNT_ONE, 60), STAmount(CURRENCY_ONE, ACCOUNT_ONE, 3), uint160(), ACCOUNT_XRP).getText() != "20")
|
||||
BOOST_FAIL("STAmount divide fail");
|
||||
|
||||
STAmount a1(CURRENCY_ONE, ACCOUNT_ONE, 60), a2 (CURRENCY_ONE, ACCOUNT_ONE, 10, -1);
|
||||
|
||||
@@ -42,7 +42,7 @@ Application::Application() :
|
||||
mNetOps(mIOService, &mMasterLedger), mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300),
|
||||
mSNTPClient(mAuxService), mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL),
|
||||
mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mSweepTimer(mAuxService)
|
||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mSweepTimer(mAuxService), mRPCHandler(&mNetOps)
|
||||
{
|
||||
RAND_bytes(mNonce256.begin(), mNonce256.size());
|
||||
RAND_bytes(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "SNTPClient.h"
|
||||
#include "../database/database.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include "RPCHandler.h"
|
||||
|
||||
class RPCDoor;
|
||||
class PeerDoor;
|
||||
@@ -55,6 +55,7 @@ class Application
|
||||
HashedObjectStore mHashedObjectStore;
|
||||
SNTPClient mSNTPClient;
|
||||
JobQueue mJobQueue;
|
||||
RPCHandler mRPCHandler;
|
||||
|
||||
DatabaseCon *mRpcDB, *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
|
||||
|
||||
@@ -96,6 +97,8 @@ public:
|
||||
ValidationCollection& getValidations() { return mValidations; }
|
||||
JobQueue& getJobQueue() { return mJobQueue; }
|
||||
SuppressionTable& getSuppression() { return mSuppressions; }
|
||||
RPCHandler& getRPCHandler() { return mRPCHandler; }
|
||||
|
||||
|
||||
bool isNew(const uint256& s) { return mSuppressions.addSuppression(s); }
|
||||
bool isNew(const uint256& s, uint64 p) { return mSuppressions.addSuppressionPeer(s, p); }
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#define SECTION_VALIDATORS "validators"
|
||||
#define SECTION_VALIDATORS_SITE "validators_site"
|
||||
|
||||
// Fees are in XNS.
|
||||
// Fees are in XRP.
|
||||
#define DEFAULT_FEE_DEFAULT 10
|
||||
#define DEFAULT_FEE_ACCOUNT_CREATE 1000*SYSTEM_CURRENCY_PARTS
|
||||
#define DEFAULT_FEE_NICKNAME_CREATE 1000
|
||||
@@ -165,6 +165,8 @@ void Config::setup(const std::string& strConf)
|
||||
|
||||
void Config::load()
|
||||
{
|
||||
std::cout << "Loading: " << CONFIG_FILE << std::endl;
|
||||
|
||||
std::ifstream ifsConfig(CONFIG_FILE.c_str(), std::ios::in);
|
||||
|
||||
if (!ifsConfig)
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#define SYSTEM_NAME "ripple"
|
||||
#define SYSTEM_CURRENCY_CODE "XNS"
|
||||
#define SYSTEM_CURRENCY_CODE "XRP"
|
||||
#define SYSTEM_CURRENCY_PRECISION 6
|
||||
#define SYSTEM_CURRENCY_CODE_RIPPLE "XNR"
|
||||
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
|
||||
|
||||
#define SYSTEM_CURRENCY_GIFT 1000ull
|
||||
#define SYSTEM_CURRENCY_USERS 100000000ull
|
||||
|
||||
@@ -46,7 +46,7 @@ Interpreter::Interpreter()
|
||||
mFunctionTable[CANCEL_OP]=new SubOp();
|
||||
mFunctionTable[BLOCK_OP]=new SubOp();
|
||||
mFunctionTable[BLOCK_END_OP]=new SubOp();
|
||||
mFunctionTable[SEND_XNS_OP]=new SendXNSOp();
|
||||
mFunctionTable[SEND_XRP_OP]=new SendXRPOp();
|
||||
/*
|
||||
mFunctionTable[SEND_OP]=new SendOp();
|
||||
mFunctionTable[REMOVE_CONTRACT_OP]=new SubOp();
|
||||
@@ -63,7 +63,7 @@ Interpreter::Interpreter()
|
||||
mFunctionTable[GET_LEDGER_TIME_OP]=new SubOp();
|
||||
mFunctionTable[GET_LEDGER_NUM_OP]=new SubOp();
|
||||
mFunctionTable[GET_RAND_FLOAT_OP]=new SubOp();
|
||||
mFunctionTable[GET_XNS_ESCROWED_OP]=new SubOp();
|
||||
mFunctionTable[GET_XRP_ESCROWED_OP]=new SubOp();
|
||||
mFunctionTable[GET_RIPPLE_ESCROWED_OP]=new SubOp();
|
||||
mFunctionTable[GET_RIPPLE_ESCROWED_CURRENCY_OP]=new SubOp();
|
||||
mFunctionTable[GET_RIPPLE_ESCROWED_ISSUER]=new GetRippleEscrowedIssuerOp();
|
||||
|
||||
@@ -39,12 +39,12 @@ public:
|
||||
STOP_OP, CANCEL_OP,
|
||||
|
||||
BLOCK_OP, BLOCK_END_OP,
|
||||
SEND_XNS_OP,SEND_OP,REMOVE_CONTRACT_OP,FEE_OP,CHANGE_CONTRACT_OWNER_OP,
|
||||
SEND_XRP_OP,SEND_OP,REMOVE_CONTRACT_OP,FEE_OP,CHANGE_CONTRACT_OWNER_OP,
|
||||
STOP_REMOVE_OP,
|
||||
SET_DATA_OP,GET_DATA_OP, GET_NUM_DATA_OP,
|
||||
SET_REGISTER_OP,GET_REGISTER_OP,
|
||||
GET_ISSUER_ID_OP, GET_OWNER_ID_OP, GET_LEDGER_TIME_OP, GET_LEDGER_NUM_OP, GET_RAND_FLOAT_OP,
|
||||
GET_XNS_ESCROWED_OP, GET_RIPPLE_ESCROWED_OP, GET_RIPPLE_ESCROWED_CURRENCY_OP, GET_RIPPLE_ESCROWED_ISSUER,
|
||||
GET_XRP_ESCROWED_OP, GET_RIPPLE_ESCROWED_OP, GET_RIPPLE_ESCROWED_CURRENCY_OP, GET_RIPPLE_ESCROWED_ISSUER,
|
||||
GET_ACCEPT_DATA_OP, GET_ACCEPTOR_ID_OP, GET_CONTRACT_ID_OP,
|
||||
NUM_OF_OPS };
|
||||
|
||||
|
||||
@@ -563,7 +563,7 @@ Json::Value Ledger::getJson(int options)
|
||||
}
|
||||
else
|
||||
ledger["closed"] = false;
|
||||
if (mTransactionMap && (full || ((options & LEDGER_JSON_DUMP_TXNS) != 0)))
|
||||
if (mTransactionMap && (full || ((options & LEDGER_JSON_DUMP_TXRP) != 0)))
|
||||
{
|
||||
Json::Value txns(Json::arrayValue);
|
||||
SHAMapTreeNode::TNType type;
|
||||
|
||||
@@ -35,7 +35,7 @@ enum LedgerStateParms
|
||||
lepERROR = 32, // error
|
||||
};
|
||||
|
||||
#define LEDGER_JSON_DUMP_TXNS 0x10000000
|
||||
#define LEDGER_JSON_DUMP_TXRP 0x10000000
|
||||
#define LEDGER_JSON_DUMP_STATE 0x20000000
|
||||
#define LEDGER_JSON_FULL 0x40000000
|
||||
|
||||
|
||||
@@ -1182,7 +1182,7 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
||||
{
|
||||
Log(lsTRACE) << "newLCL";
|
||||
Json::Value p;
|
||||
newLCL->addJson(p, LEDGER_JSON_DUMP_TXNS | LEDGER_JSON_DUMP_STATE);
|
||||
newLCL->addJson(p, LEDGER_JSON_DUMP_TXRP | LEDGER_JSON_DUMP_STATE);
|
||||
Log(lsTRACE) << p;
|
||||
}
|
||||
|
||||
|
||||
@@ -447,9 +447,8 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
|
||||
it != end; ++it)
|
||||
entryModify(it->second);
|
||||
|
||||
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
|
||||
|
||||
mSet.addRaw(s, result);
|
||||
cLog(lsTRACE) << "Metadata:" << mSet.getJson(0);
|
||||
}
|
||||
|
||||
// <-- uNodeDir: For deletion, present to make dirDelete efficient.
|
||||
|
||||
@@ -113,7 +113,7 @@ Ledger::pointer LedgerMaster::closeLedger(bool recover)
|
||||
TER LedgerMaster::doTransaction(const SerializedTransaction& txn, TransactionEngineParams params)
|
||||
{
|
||||
TER result = mEngine.applyTransaction(txn, params);
|
||||
theApp->getOPs().pubTransaction(mEngine.getLedger(), txn, result);
|
||||
theApp->getOPs().pubProposedTransaction(mEngine.getLedger(), txn, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -785,7 +785,7 @@ bool NetworkOPs::hasTXSet(const boost::shared_ptr<Peer>& peer, const uint256& se
|
||||
|
||||
void NetworkOPs::mapComplete(const uint256& hash, SHAMap::ref map)
|
||||
{
|
||||
if (!haveConsensusObject())
|
||||
if (haveConsensusObject())
|
||||
mConsensus->mapComplete(hash, map, true);
|
||||
}
|
||||
|
||||
@@ -927,30 +927,25 @@ Json::Value NetworkOPs::pubBootstrapAccountInfo(Ledger::ref lpAccepted, const Ri
|
||||
return jvObj;
|
||||
}
|
||||
|
||||
void NetworkOPs::pubAccountInfo(const RippleAddress& naAccountID, const Json::Value& jvObj)
|
||||
void NetworkOPs::pubProposedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult)
|
||||
{
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
subInfoMapType::iterator simIterator = mSubAccountInfo.find(naAccountID.getAccountID());
|
||||
|
||||
if (simIterator == mSubAccountInfo.end())
|
||||
Json::Value jvObj = transJson(stTxn, terResult, false, lpCurrent, "transaction");
|
||||
|
||||
{
|
||||
// Address not found do nothing.
|
||||
nothing();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found it.
|
||||
BOOST_FOREACH(InfoSub* ispListener, simIterator->second)
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
BOOST_FOREACH(InfoSub* ispListener, mSubRTTransactions)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
|
||||
pubAccountTransaction(lpCurrent,stTxn,terResult,false);
|
||||
}
|
||||
|
||||
void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
|
||||
{
|
||||
// Don't publish to clients ledgers we don't trust.
|
||||
// TODO: we need to publish old transactions when we get reconnected to the network otherwise clients can miss transactions
|
||||
if (NetworkOPs::omDISCONNECTED == getOperatingMode())
|
||||
return;
|
||||
|
||||
@@ -972,39 +967,10 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
if (!mSubAccountTransaction.empty())
|
||||
{
|
||||
Json::Value jvAccounts(Json::arrayValue);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, getLedgerAffectedAccounts(lpAccepted->getLedgerSeq()))
|
||||
{
|
||||
jvAccounts.append(Json::Value(naAccountID.humanAccountID()));
|
||||
}
|
||||
|
||||
Json::Value jvObj(Json::objectValue);
|
||||
|
||||
jvObj["type"] = "ledgerClosedAccounts";
|
||||
jvObj["ledger_closed_index"] = lpAccepted->getLedgerSeq();
|
||||
jvObj["ledger_closed"] = lpAccepted->getHash().ToString();
|
||||
jvObj["ledger_closed_time"] = Json::Value::UInt(utFromSeconds(lpAccepted->getCloseTimeNC()));
|
||||
jvObj["accounts"] = jvAccounts;
|
||||
|
||||
BOOST_FOREACH(InfoSub* ispListener, mSubLedgerAccounts)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
bool bAll = !mSubTransaction.empty();
|
||||
bool bAccounts = !mSubAccountTransaction.empty();
|
||||
|
||||
if (bAll || bAccounts)
|
||||
// we don't lock since pubAcceptedTransaction is locking
|
||||
if (!mSubTransactions.empty() || !mSubRTTransactions.empty() || !mSubAccount.empty() || !mSubRTAccount.empty() || !mSubmitMap.empty() )
|
||||
{
|
||||
SHAMap& txSet = *lpAccepted->peekTransactionMap();
|
||||
|
||||
@@ -1015,36 +981,13 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted)
|
||||
// XXX Need to give failures too.
|
||||
TER terResult = tesSUCCESS;
|
||||
|
||||
if (bAll)
|
||||
{
|
||||
pubTransactionAll(lpAccepted, *stTxn, terResult, true);
|
||||
}
|
||||
|
||||
if (bAccounts)
|
||||
{
|
||||
pubTransactionAccounts(lpAccepted, *stTxn, terResult, true);
|
||||
}
|
||||
pubAcceptedTransaction(lpAccepted, *stTxn, terResult);
|
||||
}
|
||||
// TODO: remove old entries from the submit map
|
||||
}
|
||||
}
|
||||
|
||||
// Publish bootstrap information for accounts.
|
||||
{
|
||||
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
BOOST_FOREACH(const subInfoMapType::iterator::value_type& it, mBootAccountInfo)
|
||||
{
|
||||
Json::Value jvObj = pubBootstrapAccountInfo(lpAccepted, RippleAddress::createAccountID(it.first));
|
||||
|
||||
BOOST_FOREACH(InfoSub* ispListener, it.second)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
mBootAccountInfo.clear();
|
||||
}
|
||||
|
||||
// XXX Publish delta information for accounts.
|
||||
}
|
||||
|
||||
Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terResult, bool bAccepted, Ledger::ref lpCurrent, const std::string& strType)
|
||||
@@ -1073,103 +1016,100 @@ Json::Value NetworkOPs::transJson(const SerializedTransaction& stTxn, TER terRes
|
||||
return jvObj;
|
||||
}
|
||||
|
||||
void NetworkOPs::pubTransactionAll(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted)
|
||||
void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult)
|
||||
{
|
||||
Json::Value jvObj = transJson(stTxn, terResult, bAccepted, lpCurrent, "transaction");
|
||||
Json::Value jvObj = transJson(stTxn, terResult, true, lpCurrent, "transaction");
|
||||
|
||||
BOOST_FOREACH(InfoSub* ispListener, mSubTransaction)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
BOOST_FOREACH(InfoSub* ispListener, mSubTransactions)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
|
||||
BOOST_FOREACH(InfoSub* ispListener, mSubRTTransactions)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
|
||||
pubAccountTransaction(lpCurrent,stTxn,terResult,true);
|
||||
}
|
||||
|
||||
void NetworkOPs::pubTransactionAccounts(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted)
|
||||
|
||||
// TODO: tell the mSubmitMap people
|
||||
void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted)
|
||||
{
|
||||
boost::unordered_set<InfoSub*> usisNotify;
|
||||
boost::unordered_set<InfoSub*> notify;
|
||||
|
||||
{
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
if (!mSubAccountTransaction.empty())
|
||||
if(!bAccepted && mSubRTAccount.empty()) return;
|
||||
|
||||
if (!mSubAccount.empty() || (!mSubRTAccount.empty()) )
|
||||
{
|
||||
BOOST_FOREACH(const RippleAddress& naAccountPublic, stTxn.getAffectedAccounts())
|
||||
{
|
||||
subInfoMapIterator simiIt = mSubAccountTransaction.find(naAccountPublic.getAccountID());
|
||||
subInfoMapIterator simiIt = mSubRTAccount.find(naAccountPublic.getAccountID());
|
||||
|
||||
if (simiIt != mSubAccountTransaction.end())
|
||||
if (simiIt != mSubRTAccount.end())
|
||||
{
|
||||
BOOST_FOREACH(InfoSub* ispListener, simiIt->second)
|
||||
{
|
||||
usisNotify.insert(ispListener);
|
||||
notify.insert(ispListener);
|
||||
}
|
||||
}
|
||||
if(bAccepted)
|
||||
{
|
||||
simiIt = mSubAccount.find(naAccountPublic.getAccountID());
|
||||
|
||||
if (simiIt != mSubAccount.end())
|
||||
{
|
||||
BOOST_FOREACH(InfoSub* ispListener, simiIt->second)
|
||||
{
|
||||
notify.insert(ispListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!usisNotify.empty())
|
||||
if (!notify.empty())
|
||||
{
|
||||
Json::Value jvObj = transJson(stTxn, terResult, bAccepted, lpCurrent, "account");
|
||||
|
||||
BOOST_FOREACH(InfoSub* ispListener, usisNotify)
|
||||
BOOST_FOREACH(InfoSub* ispListener, notify)
|
||||
{
|
||||
ispListener->send(jvObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOPs::pubTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult)
|
||||
{
|
||||
boost::interprocess::sharable_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
if (!mSubTransaction.empty())
|
||||
{
|
||||
pubTransactionAll(lpCurrent, stTxn, terResult, false);
|
||||
}
|
||||
|
||||
if (!mSubAccountTransaction.empty())
|
||||
{
|
||||
pubTransactionAccounts(lpCurrent, stTxn, terResult, false);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Monitoring
|
||||
//
|
||||
|
||||
void NetworkOPs::subAccountInfo(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs)
|
||||
|
||||
|
||||
void NetworkOPs::subAccount(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs,bool rt)
|
||||
{
|
||||
subInfoMapType& subMap=mSubAccount;
|
||||
if(rt) subMap=mSubRTAccount;
|
||||
|
||||
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, vnaAccountIDs)
|
||||
{
|
||||
// Register for bootstrap info.
|
||||
subInfoMapType::iterator simIterator;
|
||||
|
||||
simIterator = mBootAccountInfo.find(naAccountID.getAccountID());
|
||||
if (simIterator == mBootAccountInfo.end())
|
||||
subInfoMapType::iterator simIterator = subMap.find(naAccountID.getAccountID());
|
||||
if (simIterator == subMap.end())
|
||||
{
|
||||
// Not found
|
||||
boost::unordered_set<InfoSub*> usisElement;
|
||||
|
||||
usisElement.insert(ispListener);
|
||||
mBootAccountInfo.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found
|
||||
simIterator->second.insert(ispListener);
|
||||
}
|
||||
|
||||
// Register for messages.
|
||||
simIterator = mSubAccountInfo.find(naAccountID.getAccountID());
|
||||
if (simIterator == mSubAccountInfo.end())
|
||||
{
|
||||
// Not found
|
||||
boost::unordered_set<InfoSub*> usisElement;
|
||||
|
||||
usisElement.insert(ispListener);
|
||||
mSubAccountInfo.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
|
||||
mSubAccount.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1179,14 +1119,16 @@ void NetworkOPs::subAccountInfo(InfoSub* ispListener, const boost::unordered_set
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOPs::unsubAccountInfo(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs)
|
||||
void NetworkOPs::unsubAccount(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs,bool rt)
|
||||
{
|
||||
subInfoMapType& subMap= rt ? mSubRTAccount : mSubAccount;
|
||||
|
||||
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, vnaAccountIDs)
|
||||
{
|
||||
subInfoMapType::iterator simIterator = mSubAccountInfo.find(naAccountID.getAccountID());
|
||||
if (simIterator == mSubAccountInfo.end())
|
||||
subInfoMapType::iterator simIterator = subMap.find(naAccountID.getAccountID());
|
||||
if (simIterator == mSubAccount.end())
|
||||
{
|
||||
// Not found. Done.
|
||||
nothing();
|
||||
@@ -1199,56 +1141,7 @@ void NetworkOPs::unsubAccountInfo(InfoSub* ispListener, const boost::unordered_s
|
||||
if (simIterator->second.empty())
|
||||
{
|
||||
// Don't need hash entry.
|
||||
mSubAccountInfo.erase(simIterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOPs::subAccountTransaction(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs)
|
||||
{
|
||||
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, vnaAccountIDs)
|
||||
{
|
||||
subInfoMapType::iterator simIterator = mSubAccountTransaction.find(naAccountID.getAccountID());
|
||||
if (simIterator == mSubAccountTransaction.end())
|
||||
{
|
||||
// Not found
|
||||
boost::unordered_set<InfoSub*> usisElement;
|
||||
|
||||
usisElement.insert(ispListener);
|
||||
mSubAccountTransaction.insert(simIterator, make_pair(naAccountID.getAccountID(), usisElement));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found
|
||||
simIterator->second.insert(ispListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkOPs::unsubAccountTransaction(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs)
|
||||
{
|
||||
boost::interprocess::scoped_lock<boost::interprocess::interprocess_upgradable_mutex> sl(mMonitorLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, vnaAccountIDs)
|
||||
{
|
||||
subInfoMapType::iterator simIterator = mSubAccountTransaction.find(naAccountID.getAccountID());
|
||||
if (simIterator == mSubAccountTransaction.end())
|
||||
{
|
||||
// Not found. Done.
|
||||
nothing();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Found
|
||||
simIterator->second.erase(ispListener);
|
||||
|
||||
if (simIterator->second.empty())
|
||||
{
|
||||
// Don't need hash entry.
|
||||
mSubAccountTransaction.erase(simIterator);
|
||||
subMap.erase(simIterator);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1300,27 +1193,39 @@ bool NetworkOPs::unsubLedger(InfoSub* ispListener)
|
||||
}
|
||||
|
||||
// <-- bool: true=added, false=already there
|
||||
bool NetworkOPs::subLedgerAccounts(InfoSub* ispListener)
|
||||
bool NetworkOPs::subServer(InfoSub* ispListener)
|
||||
{
|
||||
return mSubLedgerAccounts.insert(ispListener).second;
|
||||
return mSubServer.insert(ispListener).second;
|
||||
}
|
||||
|
||||
// <-- bool: true=erased, false=was not there
|
||||
bool NetworkOPs::unsubLedgerAccounts(InfoSub* ispListener)
|
||||
bool NetworkOPs::unsubServer(InfoSub* ispListener)
|
||||
{
|
||||
return !!mSubLedgerAccounts.erase(ispListener);
|
||||
return !!mSubServer.erase(ispListener);
|
||||
}
|
||||
|
||||
// <-- bool: true=added, false=already there
|
||||
bool NetworkOPs::subTransaction(InfoSub* ispListener)
|
||||
bool NetworkOPs::subTransactions(InfoSub* ispListener)
|
||||
{
|
||||
return mSubTransaction.insert(ispListener).second;
|
||||
return mSubTransactions.insert(ispListener).second;
|
||||
}
|
||||
|
||||
// <-- bool: true=erased, false=was not there
|
||||
bool NetworkOPs::unsubTransaction(InfoSub* ispListener)
|
||||
bool NetworkOPs::unsubTransactions(InfoSub* ispListener)
|
||||
{
|
||||
return !!mSubTransaction.erase(ispListener);
|
||||
return !!mSubTransactions.erase(ispListener);
|
||||
}
|
||||
|
||||
// <-- bool: true=added, false=already there
|
||||
bool NetworkOPs::subRTTransactions(InfoSub* ispListener)
|
||||
{
|
||||
return mSubTransactions.insert(ispListener).second;
|
||||
}
|
||||
|
||||
// <-- bool: true=erased, false=was not there
|
||||
bool NetworkOPs::unsubRTTransactions(InfoSub* ispListener)
|
||||
{
|
||||
return !!mSubTransactions.erase(ispListener);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -51,6 +51,8 @@ protected:
|
||||
typedef boost::unordered_map<uint160,boost::unordered_set<InfoSub*> >::value_type subInfoMapValue;
|
||||
typedef boost::unordered_map<uint160,boost::unordered_set<InfoSub*> >::iterator subInfoMapIterator;
|
||||
|
||||
typedef boost::unordered_map<uint160,std::pair<InfoSub*,uint32> > subSubmitMapType;
|
||||
|
||||
OperatingMode mMode;
|
||||
bool mNeedNetworkLedger;
|
||||
boost::posix_time::ptime mConnectTime;
|
||||
@@ -72,24 +74,26 @@ protected:
|
||||
|
||||
// XXX Split into more locks.
|
||||
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
|
||||
subInfoMapType mBootAccountInfo;
|
||||
subInfoMapType mSubAccountInfo;
|
||||
subInfoMapType mSubAccountTransaction;
|
||||
boost::unordered_set<InfoSub*> mSubLedger; // ledger accepteds
|
||||
boost::unordered_set<InfoSub*> mSubLedgerAccounts; // ledger accepteds + affected accounts
|
||||
boost::unordered_set<InfoSub*> mSubTransaction; // all transactions
|
||||
boost::unordered_set<InfoSub*> mSubTxMeta; // all transaction meta
|
||||
// subInfoMapType mSubTransactionAccounts;
|
||||
subInfoMapType mSubAccount;
|
||||
subInfoMapType mSubRTAccount;
|
||||
subSubmitMapType mSubmitMap;
|
||||
|
||||
boost::unordered_set<InfoSub*> mSubLedger; // accepted ledgers
|
||||
boost::unordered_set<InfoSub*> mSubServer; // when server changes connectivity state
|
||||
boost::unordered_set<InfoSub*> mSubTransactions; // all accepted transactions
|
||||
boost::unordered_set<InfoSub*> mSubRTTransactions; // all proposed and accepted transactions
|
||||
|
||||
|
||||
void setMode(OperatingMode);
|
||||
|
||||
Json::Value transJson(const SerializedTransaction& stTxn, TER terResult, bool bAccepted, Ledger::ref lpCurrent, const std::string& strType);
|
||||
void pubTransactionAll(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted);
|
||||
void pubTransactionAccounts(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted);
|
||||
bool haveConsensusObject();
|
||||
|
||||
Json::Value pubBootstrapAccountInfo(Ledger::ref lpAccepted, const RippleAddress& naAccountID);
|
||||
|
||||
void pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult);
|
||||
void pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult,bool accepted);
|
||||
|
||||
public:
|
||||
NetworkOPs(boost::asio::io_service& io_service, LedgerMaster* pLedgerMaster);
|
||||
|
||||
@@ -210,33 +214,27 @@ public:
|
||||
//
|
||||
// Monitoring: publisher side
|
||||
//
|
||||
|
||||
void pubAccountInfo(const RippleAddress& naAccountID, const Json::Value& jvObj);
|
||||
void pubLedger(Ledger::ref lpAccepted);
|
||||
void pubTransaction(Ledger::ref lpLedger, const SerializedTransaction& stTxn, TER terResult);
|
||||
void pubProposedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult);
|
||||
|
||||
|
||||
//
|
||||
// Monitoring: subscriber side
|
||||
//
|
||||
|
||||
// --> vnaAddress: empty = all
|
||||
void subAccountInfo(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs);
|
||||
void unsubAccountInfo(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs);
|
||||
|
||||
void subAccountTransaction(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs);
|
||||
void unsubAccountTransaction(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs);
|
||||
|
||||
// void subAccountChanges(InfoSub* ispListener, const uint256 uLedgerHash);
|
||||
// void unsubAccountChanges(InfoSub* ispListener);
|
||||
void subAccount(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs,bool rt);
|
||||
void unsubAccount(InfoSub* ispListener, const boost::unordered_set<RippleAddress>& vnaAccountIDs,bool rt);
|
||||
|
||||
bool subLedger(InfoSub* ispListener);
|
||||
bool unsubLedger(InfoSub* ispListener);
|
||||
|
||||
bool subLedgerAccounts(InfoSub* ispListener);
|
||||
bool unsubLedgerAccounts(InfoSub* ispListener);
|
||||
bool subServer(InfoSub* ispListener);
|
||||
bool unsubServer(InfoSub* ispListener);
|
||||
|
||||
bool subTransaction(InfoSub* ispListener);
|
||||
bool unsubTransaction(InfoSub* ispListener);
|
||||
bool subTransactions(InfoSub* ispListener);
|
||||
bool unsubTransactions(InfoSub* ispListener);
|
||||
|
||||
bool subRTTransactions(InfoSub* ispListener);
|
||||
bool unsubRTTransactions(InfoSub* ispListener);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SendXNSOp : public Operation
|
||||
class SendXRPOp : public Operation
|
||||
{
|
||||
public:
|
||||
bool work(Interpreter* interpreter)
|
||||
|
||||
@@ -20,8 +20,8 @@ OrderBookDB::OrderBookDB(Ledger::pointer ledger)
|
||||
mKnownMap[book->getBookBase()]=true;
|
||||
|
||||
if(!book->getCurrencyIn())
|
||||
{ // XNS
|
||||
mXNSOrders.push_back(book);
|
||||
{ // XRP
|
||||
mXRPOrders.push_back(book);
|
||||
}else
|
||||
{
|
||||
mIssuerMap[book->getIssuerIn()].push_back(book);
|
||||
|
||||
@@ -9,7 +9,7 @@ But for now it is probably faster to just generate it each time
|
||||
class OrderBookDB
|
||||
{
|
||||
std::vector<OrderBook::pointer> mEmptyVector;
|
||||
std::vector<OrderBook::pointer> mXNSOrders;
|
||||
std::vector<OrderBook::pointer> mXRPOrders;
|
||||
std::map<uint160, std::vector<OrderBook::pointer> > mIssuerMap;
|
||||
|
||||
std::map<uint256, bool > mKnownMap;
|
||||
@@ -17,8 +17,8 @@ class OrderBookDB
|
||||
public:
|
||||
OrderBookDB(Ledger::pointer ledger);
|
||||
|
||||
// return list of all orderbooks that want XNS
|
||||
std::vector<OrderBook::pointer>& getXNSInBooks(){ return mXNSOrders; }
|
||||
// return list of all orderbooks that want XRP
|
||||
std::vector<OrderBook::pointer>& getXRPInBooks(){ return mXRPOrders; }
|
||||
// return list of all orderbooks that want IssuerID
|
||||
std::vector<OrderBook::pointer>& getBooks(const uint160& issuerID);
|
||||
// return list of all orderbooks that want this issuerID and currencyID
|
||||
|
||||
@@ -21,18 +21,18 @@ TODO: what is a good way to come up with multiple paths?
|
||||
|
||||
|
||||
OrderDB:
|
||||
getXNSOffers();
|
||||
getXRPOffers();
|
||||
|
||||
// return list of all orderbooks that want XNS
|
||||
// return list of all orderbooks that want XRP
|
||||
// return list of all orderbooks that want IssuerID
|
||||
// return list of all orderbooks that want this issuerID and currencyID
|
||||
*/
|
||||
|
||||
/*
|
||||
Test sending to XNS
|
||||
Test XNS to XNS
|
||||
Test sending to XRP
|
||||
Test XRP to XRP
|
||||
Test offer in middle
|
||||
Test XNS to USD
|
||||
Test XRP to USD
|
||||
Test USD to EUR
|
||||
*/
|
||||
|
||||
@@ -113,7 +113,7 @@ bool Pathfinder::findPaths(int maxSearchSteps, int maxPay, STPathSet& retPathSet
|
||||
// found the destination
|
||||
|
||||
if (!ele.mCurrencyID) {
|
||||
BOOST_FOREACH(OrderBook::pointer book,mOrderBook.getXNSInBooks())
|
||||
BOOST_FOREACH(OrderBook::pointer book,mOrderBook.getXRPInBooks())
|
||||
{
|
||||
//if (!path.hasSeen(line->getAccountIDPeer().getAccountID()))
|
||||
{
|
||||
@@ -188,8 +188,8 @@ bool Pathfinder::checkComplete(STPathSet& retPathSet)
|
||||
|
||||
|
||||
// get all the options from this accountID
|
||||
// if source is XNS
|
||||
// every offer that wants XNS
|
||||
// if source is XRP
|
||||
// every offer that wants XRP
|
||||
// else
|
||||
// every ripple line that starts with the source currency
|
||||
// every offer that we can take that wants the source currency
|
||||
@@ -197,8 +197,8 @@ bool Pathfinder::checkComplete(STPathSet& retPathSet)
|
||||
void Pathfinder::addOptions(PathOption::pointer tail)
|
||||
{
|
||||
if(!tail->mCurrencyID)
|
||||
{ // source XNS
|
||||
BOOST_FOREACH(OrderBook::pointer book,mOrderBook.getXNSInBooks())
|
||||
{ // source XRP
|
||||
BOOST_FOREACH(OrderBook::pointer book,mOrderBook.getXRPInBooks())
|
||||
{
|
||||
PathOption::pointer pathOption(new PathOption(tail));
|
||||
|
||||
|
||||
@@ -1321,7 +1321,7 @@ void Peer::recvLedger(ripple::TMLedgerData& packet)
|
||||
{
|
||||
if (packet.nodes().size() <= 0)
|
||||
{
|
||||
cLog(lsWARNING) << "Ledger data with no nodes";
|
||||
cLog(lsWARNING) << "Ledger/TXset data with no nodes";
|
||||
punishPeer(PP_INVALID_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ RPCDoor::RPCDoor(boost::asio::io_service& io_service) :
|
||||
Log(lsINFO) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE;
|
||||
startListening();
|
||||
}
|
||||
RPCDoor::~RPCDoor()
|
||||
{
|
||||
Log(lsINFO) << "RPC port: " << theConfig.RPC_IP << " " << theConfig.RPC_PORT << " allow remote: " << theConfig.RPC_ALLOW_REMOTE;
|
||||
}
|
||||
|
||||
void RPCDoor::startListening()
|
||||
{
|
||||
|
||||
@@ -15,4 +15,5 @@ class RPCDoor
|
||||
bool isClientAllowed(const std::string& ip);
|
||||
public:
|
||||
RPCDoor(boost::asio::io_service& io_service);
|
||||
~RPCDoor();
|
||||
};
|
||||
|
||||
1877
src/RPCHandler.cpp
1877
src/RPCHandler.cpp
File diff suppressed because it is too large
Load Diff
@@ -28,14 +28,9 @@ class RPCHandler
|
||||
Json::Value accountFromString(const uint256& uLedger, RippleAddress& naAccount, bool& bIndex, const std::string& strIdent, const int iIndex);
|
||||
|
||||
Json::Value doAcceptLedger(const Json::Value ¶ms);
|
||||
Json::Value doAccountDomainSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountEmailSet(const Json::Value ¶ms);
|
||||
|
||||
Json::Value doAccountInfo(const Json::Value& params);
|
||||
Json::Value doAccountMessageSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountPublishSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountRateSet(const Json::Value ¶ms);
|
||||
Json::Value doAccountTransactions(const Json::Value& params);
|
||||
Json::Value doAccountWalletSet(const Json::Value ¶ms);
|
||||
Json::Value doConnect(const Json::Value& params);
|
||||
Json::Value doDataDelete(const Json::Value& params);
|
||||
Json::Value doDataFetch(const Json::Value& params);
|
||||
@@ -44,24 +39,18 @@ class RPCHandler
|
||||
Json::Value doLedger(const Json::Value& params);
|
||||
Json::Value doLogRotate(const Json::Value& params);
|
||||
Json::Value doNicknameInfo(const Json::Value& params);
|
||||
Json::Value doNicknameSet(const Json::Value& params);
|
||||
Json::Value doOfferCreate(const Json::Value& params);
|
||||
Json::Value doOfferCancel(const Json::Value& params);
|
||||
|
||||
Json::Value doOwnerInfo(const Json::Value& params);
|
||||
Json::Value doPasswordFund(const Json::Value& params);
|
||||
Json::Value doPasswordSet(const Json::Value& params);
|
||||
|
||||
Json::Value doProfile(const Json::Value& params);
|
||||
Json::Value doPeers(const Json::Value& params);
|
||||
Json::Value doRipple(const Json::Value ¶ms);
|
||||
|
||||
Json::Value doRippleLinesGet(const Json::Value ¶ms);
|
||||
Json::Value doRippleLineSet(const Json::Value& params);
|
||||
Json::Value doSend(const Json::Value& params);
|
||||
Json::Value doServerInfo(const Json::Value& params);
|
||||
Json::Value doSessionClose(const Json::Value& params);
|
||||
Json::Value doSessionOpen(const Json::Value& params);
|
||||
Json::Value doLogLevel(const Json::Value& params);
|
||||
Json::Value doStop(const Json::Value& params);
|
||||
Json::Value doTransitSet(const Json::Value& params);
|
||||
Json::Value doTx(const Json::Value& params);
|
||||
Json::Value doTxHistory(const Json::Value& params);
|
||||
Json::Value doSubmit(const Json::Value& params);
|
||||
@@ -80,9 +69,6 @@ class RPCHandler
|
||||
Json::Value doValidationSeed(const Json::Value& params);
|
||||
|
||||
Json::Value doWalletAccounts(const Json::Value& params);
|
||||
Json::Value doWalletAdd(const Json::Value& params);
|
||||
Json::Value doWalletClaim(const Json::Value& params);
|
||||
Json::Value doWalletCreate(const Json::Value& params);
|
||||
Json::Value doWalletLock(const Json::Value& params);
|
||||
Json::Value doWalletPropose(const Json::Value& params);
|
||||
Json::Value doWalletSeed(const Json::Value& params);
|
||||
@@ -91,6 +77,14 @@ class RPCHandler
|
||||
|
||||
Json::Value doLogin(const Json::Value& params);
|
||||
|
||||
Json::Value doLedgerAccept(const Json::Value& params);
|
||||
Json::Value doLedgerClosed(const Json::Value& params);
|
||||
Json::Value doLedgerCurrent(const Json::Value& params);
|
||||
Json::Value doLedgerEntry(const Json::Value& params);
|
||||
Json::Value doTransactionEntry(const Json::Value& params);
|
||||
|
||||
|
||||
void addSubmitPath(Json::Value& txJSON);
|
||||
|
||||
public:
|
||||
|
||||
@@ -160,6 +154,8 @@ public:
|
||||
Json::Value doCommand(const std::string& command, Json::Value& params,int role);
|
||||
Json::Value rpcError(int iError);
|
||||
|
||||
Json::Value handleJSONSubmit(std::string& key, Json::Value& txJSON);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1536,7 +1536,7 @@ TER PathState::pushNode(
|
||||
terResult = pushImply(
|
||||
pnCur.uAccountID, // Current account.
|
||||
pnCur.uCurrencyID, // Wanted currency.
|
||||
!!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as wanted issuer.
|
||||
!!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XRP); // Account as wanted issuer.
|
||||
|
||||
// Note: pnPrv may no longer be the immediately previous node.
|
||||
}
|
||||
@@ -1603,7 +1603,7 @@ TER PathState::pushNode(
|
||||
terResult = pushImply(
|
||||
!!pnPrv.uCurrencyID
|
||||
? ACCOUNT_ONE // Rippling, but offer's don't have an account.
|
||||
: ACCOUNT_XNS,
|
||||
: ACCOUNT_XRP,
|
||||
pnPrv.uCurrencyID,
|
||||
pnPrv.uIssuerID);
|
||||
}
|
||||
@@ -1636,8 +1636,8 @@ PathState::PathState(
|
||||
{
|
||||
const uint160 uInCurrencyID = saSendMax.getCurrency();
|
||||
const uint160 uOutCurrencyID = saSend.getCurrency();
|
||||
const uint160 uInIssuerID = !!uInCurrencyID ? saSendMax.getIssuer() : ACCOUNT_XNS;
|
||||
const uint160 uOutIssuerID = !!uOutCurrencyID ? saSend.getIssuer() : ACCOUNT_XNS;
|
||||
const uint160 uInIssuerID = !!uInCurrencyID ? saSendMax.getIssuer() : ACCOUNT_XRP;
|
||||
const uint160 uOutIssuerID = !!uOutCurrencyID ? saSend.getIssuer() : ACCOUNT_XRP;
|
||||
|
||||
lesEntries = lesSource.duplicate();
|
||||
|
||||
@@ -1665,7 +1665,7 @@ PathState::PathState(
|
||||
? uOutIssuerID == uReceiverID
|
||||
? uReceiverID
|
||||
: uOutIssuerID
|
||||
: ACCOUNT_XNS;
|
||||
: ACCOUNT_XRP;
|
||||
|
||||
// Can't just use push implied, because it can't compensate for next account.
|
||||
if (!uNxtCurrencyID // Next is XRC - will have offer next
|
||||
@@ -1717,7 +1717,7 @@ PathState::PathState(
|
||||
| STPathElement::typeIssuer,
|
||||
uReceiverID, // Receive to output
|
||||
uOutCurrencyID, // Desired currency
|
||||
!!uOutCurrencyID ? uReceiverID : ACCOUNT_XNS);
|
||||
!!uOutCurrencyID ? uReceiverID : ACCOUNT_XRP);
|
||||
}
|
||||
|
||||
if (tesSUCCESS == terStatus)
|
||||
@@ -2428,13 +2428,13 @@ void TransactionEngine::calcNodeOffer(
|
||||
{
|
||||
TER terResult = temUNKNOWN;
|
||||
|
||||
// Direct: not bridging via XNS
|
||||
// Direct: not bridging via XRP
|
||||
bool bDirectNext = true; // True, if need to load.
|
||||
uint256 uDirectQuality;
|
||||
uint256 uDirectTip = Ledger::getBookBase(uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID);
|
||||
uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip);
|
||||
|
||||
// Bridging: bridging via XNS
|
||||
// Bridging: bridging via XRP
|
||||
bool bBridge = true; // True, if bridging active. False, missing an offer.
|
||||
uint256 uBridgeQuality;
|
||||
STAmount saBridgeIn; // Amount available.
|
||||
@@ -2462,10 +2462,10 @@ void TransactionEngine::calcNodeOffer(
|
||||
|
||||
if (!uCurCurrencyID && !uPrvCurrencyID)
|
||||
{
|
||||
// Bridging: Neither currency is XNS.
|
||||
uInTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, CURRENCY_XNS, ACCOUNT_XNS);
|
||||
// Bridging: Neither currency is XRP.
|
||||
uInTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, CURRENCY_XRP, ACCOUNT_XRP);
|
||||
uInEnd = Ledger::getQualityNext(uInTip);
|
||||
uOutTip = Ledger::getBookBase(CURRENCY_XNS, ACCOUNT_XNS, uCurCurrencyID, uCurIssuerID);
|
||||
uOutTip = Ledger::getBookBase(CURRENCY_XRP, ACCOUNT_XRP, uCurCurrencyID, uCurIssuerID);
|
||||
uOutEnd = Ledger::getQualityNext(uInTip);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ enum PathFlags
|
||||
PF_ISSUE = 0x80,
|
||||
};
|
||||
|
||||
#define CURRENCY_XNS uint160(0)
|
||||
#define CURRENCY_XRP uint160(0)
|
||||
#define CURRENCY_ONE uint160(1) // Used as a place holder
|
||||
#define ACCOUNT_XNS uint160(0)
|
||||
#define ACCOUNT_XRP uint160(0)
|
||||
#define ACCOUNT_ONE uint160(1) // Used as a place holder
|
||||
|
||||
DEFINE_INSTANCE(SerializedValue);
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
virtual std::string getFullText() const;
|
||||
virtual std::string getText() const // just the value
|
||||
{ return std::string(); }
|
||||
virtual Json::Value getJson(int) const
|
||||
virtual Json::Value getJson(int /*options*/) const
|
||||
{ return getText(); }
|
||||
|
||||
virtual void add(Serializer& s) const { ; }
|
||||
@@ -209,11 +209,11 @@ class STAmount : public SerializedType
|
||||
|
||||
protected:
|
||||
uint160 mCurrency; // Compared by ==. Always update mIsNative.
|
||||
uint160 mIssuer; // Not compared by ==. 0 for XNS.
|
||||
uint160 mIssuer; // Not compared by ==. 0 for XRP.
|
||||
|
||||
uint64 mValue;
|
||||
int mOffset;
|
||||
bool mIsNative; // Always !mCurrency. Native is XNS.
|
||||
bool mIsNative; // Always !mCurrency. Native is XRP.
|
||||
bool mIsNegative;
|
||||
|
||||
void canonicalize();
|
||||
@@ -274,7 +274,7 @@ public:
|
||||
int getExponent() const { return mOffset; }
|
||||
uint64 getMantissa() const { return mValue; }
|
||||
|
||||
// When the currency is XNS, the value in raw units. S=signed
|
||||
// When the currency is XRP, the value in raw units. S=signed
|
||||
uint64 getNValue() const { if (!mIsNative) throw std::runtime_error("not native"); return mValue; }
|
||||
void setNValue(uint64 v) { if (!mIsNative) throw std::runtime_error("not native"); mValue = v; }
|
||||
int64 getSNValue() const;
|
||||
|
||||
@@ -518,9 +518,9 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
|
||||
if (bCreate && !saDstAmount.isNative())
|
||||
{
|
||||
// This restriction could be relaxed.
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: Create account may only fund XNS.";
|
||||
Log(lsINFO) << "doPayment: Invalid transaction: Create account may only fund XRP.";
|
||||
|
||||
return temCREATEXNS;
|
||||
return temCREATEXRP;
|
||||
}
|
||||
else if (!bCreate)
|
||||
{
|
||||
@@ -569,11 +569,11 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
|
||||
}
|
||||
else
|
||||
{
|
||||
// Direct XNS payment.
|
||||
// Direct XRP payment.
|
||||
|
||||
STAmount saSrcXNSBalance = mTxnAccount->getFieldAmount(sfBalance);
|
||||
STAmount saSrcXRPBalance = mTxnAccount->getFieldAmount(sfBalance);
|
||||
|
||||
if (saSrcXNSBalance < saDstAmount)
|
||||
if (saSrcXRPBalance < saDstAmount)
|
||||
{
|
||||
// Transaction might succeed, if applied in a different order.
|
||||
Log(lsINFO) << "doPayment: Delay transaction: Insufficent funds.";
|
||||
@@ -582,7 +582,7 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
|
||||
}
|
||||
else
|
||||
{
|
||||
mTxnAccount->setFieldAmount(sfBalance, saSrcXNSBalance - saDstAmount);
|
||||
mTxnAccount->setFieldAmount(sfBalance, saSrcXRPBalance - saDstAmount);
|
||||
sleDst->setFieldAmount(sfBalance, sleDst->getFieldAmount(sfBalance) + saDstAmount);
|
||||
|
||||
terResult = tesSUCCESS;
|
||||
@@ -953,7 +953,7 @@ Log(lsINFO) << boost::str(boost::format("doOfferCreate: saTakerPays=%s saTakerGe
|
||||
}
|
||||
else if (saTakerPays.isNative() && saTakerGets.isNative())
|
||||
{
|
||||
Log(lsWARNING) << "doOfferCreate: Malformed offer: XNS for XNS";
|
||||
Log(lsWARNING) << "doOfferCreate: Malformed offer: XRP for XRP";
|
||||
|
||||
terResult = temBAD_OFFER;
|
||||
}
|
||||
|
||||
@@ -455,7 +455,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
terResult = terRETRY;
|
||||
}
|
||||
|
||||
if (tesSUCCESS == terResult || isTepPartial(terResult))
|
||||
if ((tesSUCCESS == terResult) || isTepPartial(terResult))
|
||||
{
|
||||
// Transaction succeeded fully or (retries are not allowed and the transaction succeeded partially).
|
||||
Serializer m;
|
||||
|
||||
@@ -34,7 +34,7 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman)
|
||||
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
|
||||
{ temBAD_SET_ID, "temBAD_SET_ID", "Malformed." },
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence in not in the past." },
|
||||
{ temCREATEXNS, "temCREATEXNS", "Can not specify non XNS for Create." },
|
||||
{ temCREATEXRP, "temCREATEXRP", "Can not specify non XRP for Create." },
|
||||
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
|
||||
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
|
||||
{ temINSUF_FEE_P, "temINSUF_FEE_P", "Fee not allowed." },
|
||||
|
||||
@@ -36,7 +36,7 @@ enum TER // aka TransactionEngineResult
|
||||
temBAD_TRANSFER_RATE,
|
||||
temBAD_SEQUENCE,
|
||||
temBAD_SET_ID,
|
||||
temCREATEXNS,
|
||||
temCREATEXRP,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
temINSUF_FEE_P,
|
||||
|
||||
@@ -121,6 +121,7 @@ static bool compare(const STObject& o1, const STObject& o2)
|
||||
STObject TransactionMetaSet::getAsObject() const
|
||||
{
|
||||
STObject metaData(sfTransactionMetaData);
|
||||
assert(mResult != 255);
|
||||
metaData.setFieldU8(sfTransactionResult, mResult);
|
||||
metaData.addObject(mNodes);
|
||||
return metaData;
|
||||
|
||||
304
src/WSConnection.cpp
Normal file
304
src/WSConnection.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
#include "WSConnection.h"
|
||||
#include "WSHandler.h"
|
||||
|
||||
#include "../json/reader.h"
|
||||
#include "../json/writer.h"
|
||||
//
|
||||
// WSConnection
|
||||
//
|
||||
|
||||
SETUP_LOG();
|
||||
|
||||
WSConnection::~WSConnection()
|
||||
{
|
||||
mNetwork.unsubTransactions(this);
|
||||
mNetwork.unsubRTTransactions(this);
|
||||
mNetwork.unsubLedger(this);
|
||||
mNetwork.unsubServer(this);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,true);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,false);
|
||||
}
|
||||
|
||||
void WSConnection::send(const Json::Value& jvObj)
|
||||
{
|
||||
mHandler->send(mConnection, jvObj);
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
||||
Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
|
||||
{
|
||||
static struct {
|
||||
const char* pCommand;
|
||||
doFuncPtr dfpFunc;
|
||||
} commandsA[] = {
|
||||
// Request-Response Commands:
|
||||
{ "submit", &WSConnection::doSubmit },
|
||||
{ "subscribe", &WSConnection::doSubscribe },
|
||||
{ "unsubscribe", &WSConnection::doUnsubscribe },
|
||||
{ "rpc", &WSConnection::doRPC },
|
||||
};
|
||||
|
||||
if (!jvRequest.isMember("command"))
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
jvResult["type"] = "response";
|
||||
jvResult["result"] = "error";
|
||||
jvResult["error"] = "missingCommand";
|
||||
jvResult["command"] = jvRequest;
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
std::string strCommand = jvRequest["command"].asString();
|
||||
|
||||
int i = NUMBER(commandsA);
|
||||
|
||||
while (i-- && strCommand != commandsA[i].pCommand)
|
||||
;
|
||||
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
jvResult["type"] = "response";
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
jvResult["error"] = "unknownCommand"; // Unknown command.
|
||||
}
|
||||
else
|
||||
{
|
||||
(this->*(commandsA[i].dfpFunc))(jvResult, jvRequest);
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("id"))
|
||||
{
|
||||
jvResult["id"] = jvRequest["id"];
|
||||
}
|
||||
|
||||
if (jvResult.isMember("error"))
|
||||
{
|
||||
jvResult["result"] = "error";
|
||||
jvResult["request"] = jvRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["result"] = "success";
|
||||
}
|
||||
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
boost::unordered_set<RippleAddress> WSConnection::parseAccountIds(const Json::Value& jvArray)
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaResult;
|
||||
|
||||
for (Json::Value::const_iterator it = jvArray.begin(); it != jvArray.end(); it++)
|
||||
{
|
||||
RippleAddress naString;
|
||||
|
||||
if (!(*it).isString() || !naString.setAccountID((*it).asString()))
|
||||
{
|
||||
usnaResult.clear();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) usnaResult.insert(naString);
|
||||
}
|
||||
}
|
||||
|
||||
return usnaResult;
|
||||
}
|
||||
|
||||
//
|
||||
// Commands
|
||||
//
|
||||
|
||||
/*
|
||||
server : Sends a message anytime the server status changes such as network connectivity.
|
||||
ledger : Sends a message at every ledger close.
|
||||
transactions : Sends a message for every transaction that makes it into a ledger.
|
||||
rt_transactions
|
||||
accounts
|
||||
rt_accounts
|
||||
*/
|
||||
void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString() )
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetwork.subServer(this);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetwork.subLedger(this);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetwork.subTransactions(this);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetwork.subRTTransactions(this);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
if ((*it).isString() )
|
||||
{
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetwork.unsubServer(this);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetwork.unsubLedger(this);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetwork.unsubTransactions(this);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetwork.unsubRTTransactions(this);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
}
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WSConnection::doRPC(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("rpc_command") )
|
||||
{
|
||||
jvResult=theApp->getRPCHandler().doCommand(jvRequest["rpc_command"].asString(),jvRequest["params"],RPCHandler::GUEST);
|
||||
|
||||
}else jvResult["error"] = "fieldNotCommand";
|
||||
|
||||
}
|
||||
|
||||
// XXX Currently requires secret. Allow signed transaction as an alternative.
|
||||
void WSConnection::doSubmit(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("tx_json"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundTransaction";
|
||||
}else if (!jvRequest.isMember("key"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundKey";
|
||||
}else
|
||||
{
|
||||
jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest["key"].asString(),jvRequest["tx_json"]);
|
||||
|
||||
// TODO: track the transaction mNetwork.subSubmit(this, jvResult["tx hash"] );
|
||||
}
|
||||
}
|
||||
|
||||
55
src/WSConnection.h
Normal file
55
src/WSConnection.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#include "../websocketpp/src/sockets/tls.hpp"
|
||||
#include "../websocketpp/src/websocketpp.hpp"
|
||||
#include "WSDoor.h"
|
||||
#include "Application.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "NetworkOPs.h"
|
||||
|
||||
template <typename endpoint_type>
|
||||
class WSServerHandler;
|
||||
//
|
||||
// Storage for connection specific info
|
||||
// - Subscriptions
|
||||
//
|
||||
class WSConnection : public InfoSub
|
||||
{
|
||||
public:
|
||||
typedef websocketpp::WSDOOR_SERVER::handler::connection_ptr connection_ptr;
|
||||
typedef websocketpp::WSDOOR_SERVER::handler::message_ptr message_ptr;
|
||||
|
||||
protected:
|
||||
typedef void (WSConnection::*doFuncPtr)(Json::Value& jvResult, Json::Value &jvRequest);
|
||||
|
||||
boost::mutex mLock;
|
||||
boost::unordered_set<RippleAddress> mSubAccountInfo;
|
||||
boost::unordered_set<RippleAddress> mSubAccountTransaction;
|
||||
|
||||
WSServerHandler<websocketpp::WSDOOR_SERVER>* mHandler;
|
||||
connection_ptr mConnection;
|
||||
NetworkOPs& mNetwork;
|
||||
|
||||
public:
|
||||
// WSConnection()
|
||||
// : mHandler((WSServerHandler<websocketpp::WSDOOR_SERVER>*)(NULL)),
|
||||
// mConnection(connection_ptr()) { ; }
|
||||
|
||||
WSConnection(WSServerHandler<websocketpp::WSDOOR_SERVER>* wshpHandler, connection_ptr cpConnection)
|
||||
: mHandler(wshpHandler), mConnection(cpConnection), mNetwork(theApp->getOPs()) { ; }
|
||||
|
||||
virtual ~WSConnection();
|
||||
|
||||
// Implement overridden functions from base class:
|
||||
void send(const Json::Value& jvObj);
|
||||
|
||||
// Utilities
|
||||
Json::Value invokeCommand(Json::Value& jvRequest);
|
||||
boost::unordered_set<RippleAddress> parseAccountIds(const Json::Value& jvArray);
|
||||
|
||||
// Commands
|
||||
void doSubmit(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doRPC(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
|
||||
};
|
||||
1077
src/WSDoor.cpp
1077
src/WSDoor.cpp
File diff suppressed because it is too large
Load Diff
124
src/WSHandler.h
Normal file
124
src/WSHandler.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#ifndef __WSHANDLER__
|
||||
#define __WSHANDLER__
|
||||
|
||||
class WSConnection;
|
||||
|
||||
// A single instance of this object is made.
|
||||
// This instance dispatches all events. There is no per connection persistence.
|
||||
template <typename endpoint_type>
|
||||
class WSServerHandler : public endpoint_type::handler
|
||||
{
|
||||
public:
|
||||
typedef typename endpoint_type::handler::connection_ptr connection_ptr;
|
||||
typedef typename endpoint_type::handler::message_ptr message_ptr;
|
||||
|
||||
// Private reasons to close.
|
||||
enum {
|
||||
crTooSlow = 4000, // Client is too slow.
|
||||
};
|
||||
|
||||
private:
|
||||
boost::shared_ptr<boost::asio::ssl::context> mCtx;
|
||||
|
||||
protected:
|
||||
boost::mutex mMapLock;
|
||||
// For each connection maintain an associated object to track subscriptions.
|
||||
boost::unordered_map<connection_ptr, boost::shared_ptr<WSConnection> > mMap;
|
||||
|
||||
public:
|
||||
WSServerHandler(boost::shared_ptr<boost::asio::ssl::context> spCtx) : mCtx(spCtx) {}
|
||||
|
||||
boost::shared_ptr<boost::asio::ssl::context> on_tls_init()
|
||||
{
|
||||
return mCtx;
|
||||
}
|
||||
|
||||
void send(connection_ptr cpClient, message_ptr mpMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
cpClient->send(mpMessage->get_payload(), mpMessage->get_opcode());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cpClient->close(websocketpp::close::status::value(crTooSlow), std::string("Client is too slow."));
|
||||
}
|
||||
}
|
||||
|
||||
void send(connection_ptr cpClient, const std::string& strMessage)
|
||||
{
|
||||
try
|
||||
{
|
||||
cLog(lsDEBUG) << "Ws:: Sending '" << strMessage << "'";
|
||||
|
||||
cpClient->send(strMessage);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cpClient->close(websocketpp::close::status::value(crTooSlow), std::string("Client is too slow."));
|
||||
}
|
||||
}
|
||||
|
||||
void send(connection_ptr cpClient, const Json::Value& jvObj)
|
||||
{
|
||||
Json::FastWriter jfwWriter;
|
||||
|
||||
// cLog(lsDEBUG) << "Ws:: Object '" << jfwWriter.write(jvObj) << "'";
|
||||
|
||||
send(cpClient, jfwWriter.write(jvObj));
|
||||
}
|
||||
|
||||
void on_open(connection_ptr cpClient)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMapLock);
|
||||
|
||||
mMap[cpClient] = boost::make_shared<WSConnection>(this, cpClient);
|
||||
}
|
||||
|
||||
void on_close(connection_ptr cpClient)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mMapLock);
|
||||
|
||||
mMap.erase(cpClient);
|
||||
}
|
||||
|
||||
void on_message(connection_ptr cpClient, message_ptr mpMessage)
|
||||
{
|
||||
Json::Value jvRequest;
|
||||
Json::Reader jrReader;
|
||||
|
||||
if (mpMessage->get_opcode() != websocketpp::frame::opcode::TEXT)
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
jvResult["type"] = "error";
|
||||
jvResult["error"] = "wsTextRequired"; // We only accept text messages.
|
||||
|
||||
send(cpClient, jvResult);
|
||||
}
|
||||
else if (!jrReader.parse(mpMessage->get_payload(), jvRequest) || jvRequest.isNull() || !jvRequest.isObject())
|
||||
{
|
||||
Json::Value jvResult(Json::objectValue);
|
||||
|
||||
jvResult["type"] = "error";
|
||||
jvResult["error"] = "jsonInvalid"; // Received invalid json.
|
||||
jvResult["value"] = mpMessage->get_payload();
|
||||
|
||||
send(cpClient, jvResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
send(cpClient, mMap[cpClient]->invokeCommand(jvRequest));
|
||||
}
|
||||
}
|
||||
|
||||
// Respond to http requests.
|
||||
void http(connection_ptr cpClient)
|
||||
{
|
||||
cpClient->set_body(
|
||||
"<!DOCTYPE html><html><head><title>" SYSTEM_NAME " Test</title></head>"
|
||||
"<body><h1>" SYSTEM_NAME " Test</h1><p>This page shows http(s) connectivity is working.</p></body></html>");
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user