This commit is contained in:
Andrey Fedorov
2012-11-05 10:08:46 -08:00
36 changed files with 1333 additions and 2681 deletions

View File

@@ -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" />

View File

@@ -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" />

View File

@@ -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);

View File

@@ -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));

View File

@@ -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); }

View File

@@ -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)

View File

@@ -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

View File

@@ -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();

View File

@@ -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 };

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -276,7 +276,7 @@ public:
}
};
class SendXNSOp : public Operation
class SendXRPOp : public Operation
{
public:
bool work(Interpreter* interpreter)

View File

@@ -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);

View File

@@ -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

View File

@@ -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));

View File

@@ -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;
}

View File

@@ -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()
{

View File

@@ -15,4 +15,5 @@ class RPCDoor
bool isClientAllowed(const std::string& ip);
public:
RPCDoor(boost::asio::io_service& io_service);
~RPCDoor();
};

File diff suppressed because it is too large Load Diff

View File

@@ -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 &params);
Json::Value doAccountDomainSet(const Json::Value &params);
Json::Value doAccountEmailSet(const Json::Value &params);
Json::Value doAccountInfo(const Json::Value& params);
Json::Value doAccountMessageSet(const Json::Value &params);
Json::Value doAccountPublishSet(const Json::Value &params);
Json::Value doAccountRateSet(const Json::Value &params);
Json::Value doAccountTransactions(const Json::Value& params);
Json::Value doAccountWalletSet(const Json::Value &params);
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 &params);
Json::Value doRippleLinesGet(const Json::Value &params);
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

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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." },

View File

@@ -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,

View File

@@ -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
View 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
View 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);
};

File diff suppressed because it is too large Load Diff

124
src/WSHandler.h Normal file
View 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