mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
mostly working
This commit is contained in:
@@ -91,7 +91,7 @@ Ledger::pointer LedgerMaster::closeLedger()
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -918,32 +918,26 @@ 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;
|
||||
|
||||
@@ -965,37 +959,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);
|
||||
|
||||
if (!mSubTransactions.empty() || !mSubRTTransactions.empty() || !mSubAccount.empty() || !mSubRTAccount.empty())
|
||||
// we don't lock since pubAcceptedTransaction is locking
|
||||
if (!mSubTransactions.empty() || !mSubRTTransactions.empty() || !mSubAccount.empty() || !mSubRTAccount.empty() || !mSubmitMap.empty() )
|
||||
{
|
||||
SHAMap& txSet = *lpAccepted->peekTransactionMap();
|
||||
|
||||
@@ -1006,36 +973,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)
|
||||
@@ -1085,6 +1029,7 @@ void NetworkOPs::pubAcceptedTransaction(Ledger::ref lpCurrent, const SerializedT
|
||||
}
|
||||
|
||||
|
||||
// TODO: tell the mSubmitMap people
|
||||
void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted)
|
||||
{
|
||||
boost::unordered_set<InfoSub*> notify;
|
||||
@@ -1138,39 +1083,25 @@ void NetworkOPs::pubAccountTransaction(Ledger::ref lpCurrent, const SerializedTr
|
||||
// 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
|
||||
{
|
||||
@@ -1180,14 +1111,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();
|
||||
@@ -1200,56 +1133,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1301,25 +1185,37 @@ 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 mSubTransactions.insert(ispListener).second;
|
||||
}
|
||||
|
||||
// <-- bool: true=erased, false=was not there
|
||||
bool NetworkOPs::unsubTransaction(InfoSub* ispListener)
|
||||
bool NetworkOPs::unsubTransactions(InfoSub* 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -74,9 +76,10 @@ protected:
|
||||
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
|
||||
subInfoMapType mSubAccount;
|
||||
subInfoMapType mSubRTAccount;
|
||||
subSubmitMapType mSubmitMap;
|
||||
|
||||
boost::unordered_set<InfoSub*> mSubLedger; // accepted ledgers
|
||||
boost::unordered_set<InfoSub*> mSubLedgerAccounts; // accepted ledgers + affected accounts
|
||||
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
|
||||
|
||||
@@ -211,31 +214,26 @@ public:
|
||||
// Monitoring: publisher side
|
||||
//
|
||||
void pubLedger(Ledger::ref lpAccepted);
|
||||
void pubProposedTransaction(Ledger::ref lpCurrent, const SerializedTransaction& stTxn, TER terResult, bool bAccepted);
|
||||
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
|
||||
|
||||
@@ -248,7 +248,7 @@ Json::Value RPCHandler::authorize(const uint256& uLedger,
|
||||
|
||||
if (saSrcBalance < saFee)
|
||||
{
|
||||
cLog(lsINFO) << "authorize: Insufficent funds for fees: fee=" << saFee.getText() << " balance=" << saSrcBalance.getText();
|
||||
cLog(lsINFO) << "authorize: Insufficient funds for fees: fee=" << saFee.getText() << " balance=" << saSrcBalance.getText();
|
||||
|
||||
return rpcError(rpcINSUF_FUNDS);
|
||||
}
|
||||
@@ -1638,13 +1638,65 @@ Json::Value RPCHandler::handleJSONSubmit(std::string& key, Json::Value& txJSON)
|
||||
}
|
||||
if (!naAccount.setAccountID(txJSON["Account"].asString()))
|
||||
{
|
||||
return rpcError(rpcSRC_ACT_MISSING);
|
||||
return rpcError(rpcSRC_ACT_MALFORMED);
|
||||
}
|
||||
|
||||
AccountState::pointer asSrc = mNetOps->getAccountState(uint256(0), naAccount);
|
||||
|
||||
if( txJSON["type"]=="Payment")
|
||||
{
|
||||
txJSON["TransactionType"]=0;
|
||||
|
||||
if(!txJSON.isMember("Fee"))
|
||||
{
|
||||
RippleAddress naDstAccountID;
|
||||
if (!naDstAccountID.setAccountID(txJSON["Destination"].asString()))
|
||||
{
|
||||
return rpcError(rpcDST_ACT_MALFORMED);
|
||||
}
|
||||
|
||||
if(mNetOps->getAccountState(uint256(0), naDstAccountID))
|
||||
txJSON["Fee"]=(int)theConfig.FEE_DEFAULT;
|
||||
else txJSON["Fee"]=(int)theConfig.FEE_ACCOUNT_CREATE;
|
||||
}
|
||||
/* TODO: pathfinding
|
||||
if(!txJSON.isMember("Paths"))
|
||||
{
|
||||
if(txJSON["Amount"].isObject() || txJSON.isMember("SendMax") )
|
||||
{ // we need a ripple path
|
||||
STPathSet spsPaths;
|
||||
uint160 srcCurrencyID;
|
||||
|
||||
STAmount::currencyFromString(srcCurrencyID, sSrcCurrency);
|
||||
Pathfinder pf(naSrcAccountID, naDstAccountID, srcCurrencyID, saDstAmount);
|
||||
pf.findPaths(5, 1, spsPaths);
|
||||
txJSON["Paths"]=spsPaths.getJson();
|
||||
if(txJSON.isMember("Flags")) txJSON["Flags"]=txJSON["Flags"].asUInt() | 2;
|
||||
else txJSON["Flags"]=2;
|
||||
}
|
||||
}*/
|
||||
}else if( txJSON["type"]=="OfferCreate" )
|
||||
{
|
||||
txJSON["TransactionType"]=7;
|
||||
if(!txJSON.isMember("Fee")) txJSON["Fee"]=(int)theConfig.FEE_DEFAULT;
|
||||
}else if( txJSON["type"]=="TrustSet")
|
||||
{
|
||||
txJSON["TransactionType"]=20;
|
||||
if(!txJSON.isMember("Fee")) txJSON["Fee"]=(int)theConfig.FEE_DEFAULT;
|
||||
}else if( txJSON["type"]=="OfferCancel")
|
||||
{
|
||||
txJSON["TransactionType"]=8;
|
||||
if(!txJSON.isMember("Fee")) txJSON["Fee"]=(int)theConfig.FEE_DEFAULT;
|
||||
}
|
||||
|
||||
txJSON.removeMember("type");
|
||||
|
||||
if(!txJSON.isMember("Sequence")) txJSON["Sequence"]=asSrc->getSeq();
|
||||
if(!txJSON.isMember("Flags")) txJSON["Flags"]=0;
|
||||
|
||||
Ledger::pointer lpCurrent = mNetOps->getCurrentLedger();
|
||||
SLE::pointer sleAccountRoot = mNetOps->getSLE(lpCurrent, Ledger::getAccountRootIndex(naAccount.getAccountID()));
|
||||
|
||||
|
||||
if (!sleAccountRoot)
|
||||
{
|
||||
// XXX Ignore transactions for accounts not created.
|
||||
@@ -2005,6 +2057,24 @@ Json::Value RPCHandler::doTx(const Json::Value& params)
|
||||
return rpcError(rpcNOT_IMPL);
|
||||
}
|
||||
|
||||
Json::Value RPCHandler::doLedgerClosed(const Json::Value& params)
|
||||
{
|
||||
Json::Value jvResult;
|
||||
uint256 uLedger = mNetOps->getClosedLedger();
|
||||
|
||||
jvResult["ledger_closed_index"] = mNetOps->getLedgerID(uLedger);
|
||||
jvResult["ledger_closed"] = uLedger.ToString();
|
||||
//jvResult["ledger_closed_time"] = uLedger.
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
Json::Value RPCHandler::doLedgerCurrent(const Json::Value& params)
|
||||
{
|
||||
Json::Value jvResult;
|
||||
jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID();
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
// ledger [id|current|lastclosed] [full]
|
||||
Json::Value RPCHandler::doLedger(const Json::Value& params)
|
||||
{
|
||||
@@ -2837,4 +2907,322 @@ Json::Value RPCHandler::doUnlLoad(const Json::Value& params)
|
||||
return "loading";
|
||||
}
|
||||
|
||||
Json::Value RPCHandler::doLedgerAccept(const Json::Value& )
|
||||
{
|
||||
Json::Value jvResult;
|
||||
if (!theConfig.RUN_STANDALONE)
|
||||
{
|
||||
jvResult["error"] = "notStandAlone";
|
||||
}
|
||||
else
|
||||
{
|
||||
mNetOps->acceptLedger();
|
||||
|
||||
jvResult["ledger_current_index"] = mNetOps->getCurrentLedgerID();
|
||||
}
|
||||
return(jvResult);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Json::Value RPCHandler::doTransactionEntry(const Json::Value& params)
|
||||
{
|
||||
Json::Value jvResult;
|
||||
/* LATER
|
||||
if (!jvRequest.isMember("transaction"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundTransaction";
|
||||
}
|
||||
if (!jvRequest.isMember("ledger_closed"))
|
||||
{
|
||||
jvResult["error"] = "notYetImplemented"; // XXX We don't support any transaction yet.
|
||||
}
|
||||
else
|
||||
{
|
||||
uint256 uTransID;
|
||||
// XXX Relying on trusted WSS client. Would be better to have a strict routine, returning success or failure.
|
||||
uTransID.SetHex(jvRequest["transaction"].asString());
|
||||
|
||||
uint256 uLedgerID;
|
||||
// XXX Relying on trusted WSS client. Would be better to have a strict routine, returning success or failure.
|
||||
uLedgerID.SetHex(jvRequest["ledger_closed"].asString());
|
||||
|
||||
Ledger::pointer lpLedger = theApp->getMasterLedger().getLedgerByHash(uLedgerID);
|
||||
|
||||
if (!lpLedger) {
|
||||
jvResult["error"] = "ledgerNotFound";
|
||||
}
|
||||
else
|
||||
{
|
||||
Transaction::pointer tpTrans;
|
||||
TransactionMetaSet::pointer tmTrans;
|
||||
|
||||
if (!lpLedger-> getTransaction(uTransID, tpTrans, tmTrans))
|
||||
{
|
||||
jvResult["error"] = "transactionNotFound";
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["transaction"] = tpTrans->getJson(0);
|
||||
jvResult["metadata"] = tmTrans->getJson(0);
|
||||
// 'accounts'
|
||||
// 'engine_...'
|
||||
// 'ledger_...'
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Json::Value RPCHandler::doLedgerEntry(const Json::Value& params)
|
||||
{
|
||||
Json::Value jvResult;
|
||||
/* TODO
|
||||
|
||||
uint256 uLedger = jvRequest.isMember("ledger_closed") ? uint256(jvRequest["ledger_closed"].asString()) : 0;
|
||||
uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0;
|
||||
|
||||
Ledger::pointer lpLedger;
|
||||
|
||||
if (!!uLedger)
|
||||
{
|
||||
// Ledger directly specified.
|
||||
lpLedger = noNetwork.getLedgerByHash(uLedger);
|
||||
|
||||
if (!lpLedger)
|
||||
{
|
||||
jvResult["error"] = "ledgerNotFound";
|
||||
return;
|
||||
}
|
||||
|
||||
uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index, override if needed.
|
||||
}
|
||||
else if (!!uLedgerIndex)
|
||||
{
|
||||
lpLedger = noNetwork.getLedgerBySeq(uLedgerIndex);
|
||||
|
||||
if (!lpLedger)
|
||||
{
|
||||
jvResult["error"] = "ledgerNotFound"; // ledger_index from future?
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to current ledger.
|
||||
lpLedger = noNetwork.getCurrentLedger();
|
||||
uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index.
|
||||
}
|
||||
|
||||
if (lpLedger->isClosed())
|
||||
{
|
||||
if (!!uLedger)
|
||||
jvResult["ledger_closed"] = uLedger.ToString();
|
||||
|
||||
jvResult["ledger_closed_index"] = uLedgerIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["ledger_current_index"] = uLedgerIndex;
|
||||
}
|
||||
|
||||
uint256 uNodeIndex;
|
||||
bool bNodeBinary = false;
|
||||
|
||||
if (jvRequest.isMember("index"))
|
||||
{
|
||||
// XXX Needs to provide proof.
|
||||
uNodeIndex.SetHex(jvRequest["index"].asString());
|
||||
bNodeBinary = true;
|
||||
}
|
||||
else if (jvRequest.isMember("account_root"))
|
||||
{
|
||||
RippleAddress naAccount;
|
||||
|
||||
if (!naAccount.setAccountID(jvRequest["account_root"].asString())
|
||||
|| !naAccount.getAccountID())
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
uNodeIndex = Ledger::getAccountRootIndex(naAccount.getAccountID());
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("directory"))
|
||||
{
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["directory"].asString());
|
||||
}
|
||||
else if (jvRequest["directory"].isMember("sub_index")
|
||||
&& !jvRequest["directory"]["sub_index"].isIntegral())
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 uSubIndex = jvRequest["directory"].isMember("sub_index")
|
||||
? jvRequest["directory"]["sub_index"].asUInt()
|
||||
: 0;
|
||||
|
||||
if (jvRequest["directory"].isMember("dir_root"))
|
||||
{
|
||||
uint256 uDirRoot;
|
||||
|
||||
uDirRoot.SetHex(jvRequest["dir_root"].asString());
|
||||
|
||||
uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex);
|
||||
}
|
||||
else if (jvRequest["directory"].isMember("owner"))
|
||||
{
|
||||
RippleAddress naOwnerID;
|
||||
|
||||
if (!naOwnerID.setAccountID(jvRequest["directory"]["owner"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint256 uDirRoot = Ledger::getOwnerDirIndex(naOwnerID.getAccountID());
|
||||
|
||||
uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("generator"))
|
||||
{
|
||||
RippleAddress naGeneratorID;
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["generator"].asString());
|
||||
}
|
||||
else if (!jvRequest["generator"].isMember("regular_seed"))
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naGeneratorID.setSeedGeneric(jvRequest["generator"]["regular_seed"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
RippleAddress na0Public; // To find the generator's index.
|
||||
RippleAddress naGenerator = RippleAddress::createGeneratorPublic(naGeneratorID);
|
||||
|
||||
na0Public.setAccountPublic(naGenerator, 0);
|
||||
|
||||
uNodeIndex = Ledger::getGeneratorIndex(na0Public.getAccountID());
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("offer"))
|
||||
{
|
||||
RippleAddress naAccountID;
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["offer"].asString());
|
||||
}
|
||||
else if (!jvRequest["offer"].isMember("account")
|
||||
|| !jvRequest["offer"].isMember("seq")
|
||||
|| !jvRequest["offer"]["seq"].isIntegral())
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naAccountID.setAccountID(jvRequest["offer"]["account"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 uSequence = jvRequest["offer"]["seq"].asUInt();
|
||||
|
||||
uNodeIndex = Ledger::getOfferIndex(naAccountID.getAccountID(), uSequence);
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("ripple_state"))
|
||||
{
|
||||
RippleAddress naA;
|
||||
RippleAddress naB;
|
||||
uint160 uCurrency;
|
||||
Json::Value jvRippleState = jvRequest["ripple_state"];
|
||||
|
||||
if (!jvRippleState.isMember("currency")
|
||||
|| !jvRippleState.isMember("accounts")
|
||||
|| !jvRippleState["accounts"].isArray()
|
||||
|| 2 != jvRippleState["accounts"].size()
|
||||
|| !jvRippleState["accounts"][0u].isString()
|
||||
|| !jvRippleState["accounts"][1u].isString()
|
||||
|| jvRippleState["accounts"][0u].asString() == jvRippleState["accounts"][1u].asString()
|
||||
) {
|
||||
|
||||
cLog(lsINFO)
|
||||
<< boost::str(boost::format("ledger_entry: ripple_state: accounts: %d currency: %d array: %d size: %d equal: %d")
|
||||
% jvRippleState.isMember("accounts")
|
||||
% jvRippleState.isMember("currency")
|
||||
% jvRippleState["accounts"].isArray()
|
||||
% jvRippleState["accounts"].size()
|
||||
% (jvRippleState["accounts"][0u].asString() == jvRippleState["accounts"][1u].asString())
|
||||
);
|
||||
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naA.setAccountID(jvRippleState["accounts"][0u].asString())
|
||||
|| !naB.setAccountID(jvRippleState["accounts"][1u].asString())) {
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else if (!STAmount::currencyFromString(uCurrency, jvRippleState["currency"].asString())) {
|
||||
jvResult["error"] = "malformedCurrency";
|
||||
}
|
||||
else
|
||||
{
|
||||
uNodeIndex = Ledger::getRippleStateIndex(naA, naB, uCurrency);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["error"] = "unknownOption";
|
||||
}
|
||||
|
||||
if (!!uNodeIndex)
|
||||
{
|
||||
SLE::pointer sleNode = noNetwork.getSLE(lpLedger, uNodeIndex);
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
// Not found.
|
||||
// XXX Should also provide proof.
|
||||
jvResult["error"] = "entryNotFound";
|
||||
}
|
||||
else if (bNodeBinary)
|
||||
{
|
||||
// XXX Should also provide proof.
|
||||
Serializer s;
|
||||
|
||||
sleNode->add(s);
|
||||
|
||||
jvResult["node_binary"] = strHex(s.peekData());
|
||||
jvResult["index"] = uNodeIndex.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["node"] = sleNode->getJson(0);
|
||||
jvResult["index"] = uNodeIndex.ToString();
|
||||
}
|
||||
}
|
||||
*/
|
||||
return jvResult;
|
||||
}
|
||||
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -92,6 +92,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);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
|
||||
@@ -11,11 +11,12 @@ SETUP_LOG();
|
||||
|
||||
WSConnection::~WSConnection()
|
||||
{
|
||||
mNetwork.unsubTransaction(this);
|
||||
mNetwork.unsubTransactions(this);
|
||||
mNetwork.unsubRTTransactions(this);
|
||||
mNetwork.unsubLedger(this);
|
||||
mNetwork.unsubLedgerAccounts(this);
|
||||
mNetwork.unsubAccountInfo(this, mSubAccountInfo);
|
||||
mNetwork.unsubAccountTransaction(this, mSubAccountTransaction);
|
||||
mNetwork.unsubServer(this);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,true);
|
||||
mNetwork.unsubAccount(this, mSubAccountInfo,false);
|
||||
}
|
||||
|
||||
void WSConnection::send(const Json::Value& jvObj)
|
||||
@@ -34,26 +35,10 @@ Json::Value WSConnection::invokeCommand(Json::Value& jvRequest)
|
||||
doFuncPtr dfpFunc;
|
||||
} commandsA[] = {
|
||||
// Request-Response Commands:
|
||||
{ "ledger_accept", &WSConnection::doLedgerAccept },
|
||||
{ "ledger_closed", &WSConnection::doLedgerClosed },
|
||||
{ "ledger_current", &WSConnection::doLedgerCurrent },
|
||||
{ "ledger_entry", &WSConnection::doLedgerEntry },
|
||||
{ "submit", &WSConnection::doSubmit },
|
||||
{ "transaction_entry", &WSConnection::doTransactionEntry },
|
||||
{ "subscribe", &WSConnection::doSubscribe },
|
||||
{ "unsubscribe", &WSConnection::doUnsubscribe },
|
||||
|
||||
// deprecated
|
||||
{ "account_info_subscribe", &WSConnection::doAccountInfoSubscribe },
|
||||
{ "account_info_unsubscribe", &WSConnection::doAccountInfoUnsubscribe },
|
||||
{ "account_transaction_subscribe", &WSConnection::doAccountTransactionSubscribe },
|
||||
{ "account_transaction_unsubscribe", &WSConnection::doAccountTransactionUnsubscribe },
|
||||
{ "ledger_accounts_subscribe", &WSConnection::doLedgerAccountsSubcribe },
|
||||
{ "ledger_accounts_unsubscribe", &WSConnection::doLedgerAccountsUnsubscribe },
|
||||
{ "server_subscribe", &WSConnection::doServerSubscribe },
|
||||
{ "server_unsubscribe", &WSConnection::doServerUnsubscribe },
|
||||
{ "transaction_subscribe", &WSConnection::doTransactionSubcribe },
|
||||
{ "transaction_unsubscribe", &WSConnection::doTransactionUnsubscribe },
|
||||
{ "submit", &WSConnection::doSubmit },
|
||||
{ "subscribe", &WSConnection::doSubscribe },
|
||||
{ "unsubscribe", &WSConnection::doUnsubscribe },
|
||||
{ "rpc", &WSConnection::doRPC },
|
||||
};
|
||||
|
||||
if (!jvRequest.isMember("command"))
|
||||
@@ -140,7 +125,6 @@ rt_transactions
|
||||
accounts
|
||||
rt_accounts
|
||||
*/
|
||||
// TODO
|
||||
void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (jvRequest.isMember("streams"))
|
||||
@@ -153,16 +137,16 @@ void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
|
||||
if(streamName=="server")
|
||||
{
|
||||
mNetwork.subLedgerAccounts(this);
|
||||
mNetwork.subServer(this);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
mNetwork.subLedgerAccounts(this);
|
||||
mNetwork.subLedger(this);
|
||||
}else if(streamName=="transactions")
|
||||
{
|
||||
mNetwork.subTransaction(this);
|
||||
mNetwork.subTransactions(this);
|
||||
}else if(streamName=="rt_transactions")
|
||||
{
|
||||
mNetwork.subTransaction(this); // TODO
|
||||
mNetwork.subRTTransactions(this);
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName);
|
||||
@@ -190,7 +174,7 @@ void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccountInfo(this, usnaAccoundIds);
|
||||
mNetwork.subAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,444 +194,86 @@ void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccountInfo(this, usnaAccoundIds);
|
||||
mNetwork.subAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void WSConnection::doAccountInfoSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("accounts"))
|
||||
if (jvRequest.isMember("streams"))
|
||||
{
|
||||
jvResult["error"] = "missingField";
|
||||
}
|
||||
else if (jvRequest["accounts"].empty())
|
||||
{
|
||||
jvResult["error"] = "emptySet";
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doAccountInfoUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("accounts"))
|
||||
{
|
||||
jvResult["error"] = "missingField";
|
||||
}
|
||||
else if (jvRequest["accounts"].empty())
|
||||
{
|
||||
jvResult["error"] = "emptySet";
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (usnaAccoundIds.empty())
|
||||
for (Json::Value::iterator it = jvRequest["streams"].begin(); it != jvRequest["streams"].end(); it++)
|
||||
{
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}
|
||||
else
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
if ((*it).isString() )
|
||||
{
|
||||
mSubAccountInfo.erase(naAccountID);
|
||||
}
|
||||
std::string streamName=(*it).asString();
|
||||
|
||||
mNetwork.unsubAccountInfo(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doAccountTransactionSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("accounts"))
|
||||
{
|
||||
jvResult["error"] = "missingField";
|
||||
}
|
||||
else if (jvRequest["accounts"].empty())
|
||||
{
|
||||
jvResult["error"] = "emptySet";
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
mSubAccountTransaction.insert(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.subAccountTransaction(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doAccountTransactionUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("accounts"))
|
||||
{
|
||||
jvResult["error"] = "missingField";
|
||||
}
|
||||
else if (jvRequest["accounts"].empty())
|
||||
{
|
||||
jvResult["error"] = "emptySet";
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{
|
||||
mSubAccountTransaction.erase(naAccountID);
|
||||
}
|
||||
|
||||
mNetwork.unsubAccountTransaction(this, usnaAccoundIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerAccountsSubcribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.subLedgerAccounts(this))
|
||||
{
|
||||
jvResult["error"] = "ledgerAccountsSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerAccountsUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.unsubLedgerAccounts(this))
|
||||
{
|
||||
jvResult["error"] = "ledgerAccountsNotSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerAccept(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!theConfig.RUN_STANDALONE)
|
||||
{
|
||||
jvResult["error"] = "notStandAlone";
|
||||
}
|
||||
else
|
||||
{
|
||||
mNetwork.acceptLedger();
|
||||
|
||||
jvResult["ledger_current_index"] = mNetwork.getCurrentLedgerID();
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerClosed(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
uint256 uLedger = mNetwork.getClosedLedger();
|
||||
|
||||
jvResult["ledger_closed_index"] = mNetwork.getLedgerID(uLedger);
|
||||
jvResult["ledger_closed"] = uLedger.ToString();
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerCurrent(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
jvResult["ledger_current_index"] = mNetwork.getCurrentLedgerID();
|
||||
}
|
||||
|
||||
void WSConnection::doLedgerEntry(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
NetworkOPs& noNetwork = mNetwork;
|
||||
uint256 uLedger = jvRequest.isMember("ledger_closed") ? uint256(jvRequest["ledger_closed"].asString()) : 0;
|
||||
uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0;
|
||||
|
||||
Ledger::pointer lpLedger;
|
||||
|
||||
if (!!uLedger)
|
||||
{
|
||||
// Ledger directly specified.
|
||||
lpLedger = noNetwork.getLedgerByHash(uLedger);
|
||||
|
||||
if (!lpLedger)
|
||||
{
|
||||
jvResult["error"] = "ledgerNotFound";
|
||||
return;
|
||||
}
|
||||
|
||||
uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index, override if needed.
|
||||
}
|
||||
else if (!!uLedgerIndex)
|
||||
{
|
||||
lpLedger = noNetwork.getLedgerBySeq(uLedgerIndex);
|
||||
|
||||
if (!lpLedger)
|
||||
{
|
||||
jvResult["error"] = "ledgerNotFound"; // ledger_index from future?
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to current ledger.
|
||||
lpLedger = noNetwork.getCurrentLedger();
|
||||
uLedgerIndex = lpLedger->getLedgerSeq(); // Set the current index.
|
||||
}
|
||||
|
||||
if (lpLedger->isClosed())
|
||||
{
|
||||
if (!!uLedger)
|
||||
jvResult["ledger_closed"] = uLedger.ToString();
|
||||
|
||||
jvResult["ledger_closed_index"] = uLedgerIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["ledger_current_index"] = uLedgerIndex;
|
||||
}
|
||||
|
||||
uint256 uNodeIndex;
|
||||
bool bNodeBinary = false;
|
||||
|
||||
if (jvRequest.isMember("index"))
|
||||
{
|
||||
// XXX Needs to provide proof.
|
||||
uNodeIndex.SetHex(jvRequest["index"].asString());
|
||||
bNodeBinary = true;
|
||||
}
|
||||
else if (jvRequest.isMember("account_root"))
|
||||
{
|
||||
RippleAddress naAccount;
|
||||
|
||||
if (!naAccount.setAccountID(jvRequest["account_root"].asString())
|
||||
|| !naAccount.getAccountID())
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
uNodeIndex = Ledger::getAccountRootIndex(naAccount.getAccountID());
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("directory"))
|
||||
{
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["directory"].asString());
|
||||
}
|
||||
else if (jvRequest["directory"].isMember("sub_index")
|
||||
&& !jvRequest["directory"]["sub_index"].isIntegral())
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint64 uSubIndex = jvRequest["directory"].isMember("sub_index")
|
||||
? jvRequest["directory"]["sub_index"].asUInt()
|
||||
: 0;
|
||||
|
||||
if (jvRequest["directory"].isMember("dir_root"))
|
||||
{
|
||||
uint256 uDirRoot;
|
||||
|
||||
uDirRoot.SetHex(jvRequest["dir_root"].asString());
|
||||
|
||||
uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex);
|
||||
}
|
||||
else if (jvRequest["directory"].isMember("owner"))
|
||||
{
|
||||
RippleAddress naOwnerID;
|
||||
|
||||
if (!naOwnerID.setAccountID(jvRequest["directory"]["owner"].asString()))
|
||||
if(streamName=="server")
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
mNetwork.unsubServer(this);
|
||||
}else if(streamName=="ledger")
|
||||
{
|
||||
uint256 uDirRoot = Ledger::getOwnerDirIndex(naOwnerID.getAccountID());
|
||||
|
||||
uNodeIndex = Ledger::getDirNodeIndex(uDirRoot, uSubIndex);
|
||||
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
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
jvResult["error"] = "malformedSteam";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("generator"))
|
||||
|
||||
if (jvRequest.isMember("rt_accounts"))
|
||||
{
|
||||
RippleAddress naGeneratorID;
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["rt_accounts"]);
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["generator"].asString());
|
||||
}
|
||||
else if (!jvRequest["generator"].isMember("regular_seed"))
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naGeneratorID.setSeedGeneric(jvRequest["generator"]["regular_seed"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
RippleAddress na0Public; // To find the generator's index.
|
||||
RippleAddress naGenerator = RippleAddress::createGeneratorPublic(naGeneratorID);
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
na0Public.setAccountPublic(naGenerator, 0);
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
uNodeIndex = Ledger::getGeneratorIndex(na0Public.getAccountID());
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,true);
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("offer"))
|
||||
|
||||
if (jvRequest.isMember("accounts"))
|
||||
{
|
||||
RippleAddress naAccountID;
|
||||
boost::unordered_set<RippleAddress> usnaAccoundIds = parseAccountIds(jvRequest["accounts"]);
|
||||
|
||||
if (!jvRequest.isObject())
|
||||
if (usnaAccoundIds.empty())
|
||||
{
|
||||
uNodeIndex.SetHex(jvRequest["offer"].asString());
|
||||
}
|
||||
else if (!jvRequest["offer"].isMember("account")
|
||||
|| !jvRequest["offer"].isMember("seq")
|
||||
|| !jvRequest["offer"]["seq"].isIntegral())
|
||||
jvResult["error"] = "malformedAccount";
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naAccountID.setAccountID(jvRequest["offer"]["account"].asString()))
|
||||
{
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 uSequence = jvRequest["offer"]["seq"].asUInt();
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
uNodeIndex = Ledger::getOfferIndex(naAccountID.getAccountID(), uSequence);
|
||||
}
|
||||
}
|
||||
else if (jvRequest.isMember("ripple_state"))
|
||||
{
|
||||
RippleAddress naA;
|
||||
RippleAddress naB;
|
||||
uint160 uCurrency;
|
||||
Json::Value jvRippleState = jvRequest["ripple_state"];
|
||||
BOOST_FOREACH(const RippleAddress& naAccountID, usnaAccoundIds)
|
||||
{
|
||||
mSubAccountInfo.insert(naAccountID);
|
||||
}
|
||||
|
||||
if (!jvRippleState.isMember("currency")
|
||||
|| !jvRippleState.isMember("accounts")
|
||||
|| !jvRippleState["accounts"].isArray()
|
||||
|| 2 != jvRippleState["accounts"].size()
|
||||
|| !jvRippleState["accounts"][0u].isString()
|
||||
|| !jvRippleState["accounts"][1u].isString()
|
||||
|| jvRippleState["accounts"][0u].asString() == jvRippleState["accounts"][1u].asString()
|
||||
) {
|
||||
|
||||
cLog(lsINFO)
|
||||
<< boost::str(boost::format("ledger_entry: ripple_state: accounts: %d currency: %d array: %d size: %d equal: %d")
|
||||
% jvRippleState.isMember("accounts")
|
||||
% jvRippleState.isMember("currency")
|
||||
% jvRippleState["accounts"].isArray()
|
||||
% jvRippleState["accounts"].size()
|
||||
% (jvRippleState["accounts"][0u].asString() == jvRippleState["accounts"][1u].asString())
|
||||
);
|
||||
|
||||
jvResult["error"] = "malformedRequest";
|
||||
}
|
||||
else if (!naA.setAccountID(jvRippleState["accounts"][0u].asString())
|
||||
|| !naB.setAccountID(jvRippleState["accounts"][1u].asString())) {
|
||||
jvResult["error"] = "malformedAddress";
|
||||
}
|
||||
else if (!STAmount::currencyFromString(uCurrency, jvRippleState["currency"].asString())) {
|
||||
jvResult["error"] = "malformedCurrency";
|
||||
}
|
||||
else
|
||||
{
|
||||
uNodeIndex = Ledger::getRippleStateIndex(naA, naB, uCurrency);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["error"] = "unknownOption";
|
||||
}
|
||||
|
||||
if (!!uNodeIndex)
|
||||
{
|
||||
SLE::pointer sleNode = noNetwork.getSLE(lpLedger, uNodeIndex);
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
// Not found.
|
||||
// XXX Should also provide proof.
|
||||
jvResult["error"] = "entryNotFound";
|
||||
}
|
||||
else if (bNodeBinary)
|
||||
{
|
||||
// XXX Should also provide proof.
|
||||
Serializer s;
|
||||
|
||||
sleNode->add(s);
|
||||
|
||||
jvResult["node_binary"] = strHex(s.peekData());
|
||||
jvResult["index"] = uNodeIndex.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["node"] = sleNode->getJson(0);
|
||||
jvResult["index"] = uNodeIndex.ToString();
|
||||
mNetwork.unsubAccount(this, usnaAccoundIds,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The objective is to allow the client to know the server's status. The only thing that show the server is fully operating is the
|
||||
// stream of ledger_closeds. Therefore, that is all that is provided. A client can drop servers that do not provide recent
|
||||
// ledger_closeds.
|
||||
void WSConnection::doServerSubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.subLedger(this))
|
||||
{
|
||||
jvResult["error"] = "serverSubscribed";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (theConfig.RUN_STANDALONE)
|
||||
jvResult["stand_alone"] = 1;
|
||||
|
||||
if (NetworkOPs::omDISCONNECTED != mNetwork.getOperatingMode()) {
|
||||
jvResult["ledger_closed"] = mNetwork.getClosedLedger().ToString();
|
||||
jvResult["ledger_current_index"] = mNetwork.getCurrentLedgerID();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doServerUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.unsubLedger(this))
|
||||
{
|
||||
jvResult["error"] = "serverNotSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doRPC(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
@@ -668,67 +294,11 @@ void WSConnection::doSubmit(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
}else if (!jvRequest.isMember("key"))
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundKey";
|
||||
}else jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest["key"].asString(),jvRequest["tx_json"]);
|
||||
}
|
||||
|
||||
void WSConnection::doTransactionEntry(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!jvRequest.isMember("transaction"))
|
||||
}else
|
||||
{
|
||||
jvResult["error"] = "fieldNotFoundTransaction";
|
||||
}
|
||||
if (!jvRequest.isMember("ledger_closed"))
|
||||
{
|
||||
jvResult["error"] = "notYetImplemented"; // XXX We don't support any transaction yet.
|
||||
}
|
||||
else
|
||||
{
|
||||
uint256 uTransID;
|
||||
// XXX Relying on trusted WSS client. Would be better to have a strict routine, returning success or failure.
|
||||
uTransID.SetHex(jvRequest["transaction"].asString());
|
||||
jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest["key"].asString(),jvRequest["tx_json"]);
|
||||
|
||||
uint256 uLedgerID;
|
||||
// XXX Relying on trusted WSS client. Would be better to have a strict routine, returning success or failure.
|
||||
uLedgerID.SetHex(jvRequest["ledger_closed"].asString());
|
||||
|
||||
Ledger::pointer lpLedger = theApp->getMasterLedger().getLedgerByHash(uLedgerID);
|
||||
|
||||
if (!lpLedger) {
|
||||
jvResult["error"] = "ledgerNotFound";
|
||||
}
|
||||
else
|
||||
{
|
||||
Transaction::pointer tpTrans;
|
||||
TransactionMetaSet::pointer tmTrans;
|
||||
|
||||
if (!lpLedger-> getTransaction(uTransID, tpTrans, tmTrans))
|
||||
{
|
||||
jvResult["error"] = "transactionNotFound";
|
||||
}
|
||||
else
|
||||
{
|
||||
jvResult["transaction"] = tpTrans->getJson(0);
|
||||
jvResult["metadata"] = tmTrans->getJson(0);
|
||||
// 'accounts'
|
||||
// 'engine_...'
|
||||
// 'ledger_...'
|
||||
}
|
||||
}
|
||||
// TODO: mNetwork.subSubmit(this, jvResult["tx hash"] );
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doTransactionSubcribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.subTransaction(this))
|
||||
{
|
||||
jvResult["error"] = "TransactionsSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
void WSConnection::doTransactionUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest)
|
||||
{
|
||||
if (!mNetwork.unsubTransaction(this))
|
||||
{
|
||||
jvResult["error"] = "TransactionsNotSubscribed";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,24 +52,4 @@ public:
|
||||
void doSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
|
||||
|
||||
|
||||
// deprecated
|
||||
void doLedgerAccept(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doLedgerClosed(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doLedgerCurrent(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doLedgerEntry(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doTransactionEntry(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
|
||||
void doAccountInfoSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doAccountInfoUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doAccountTransactionSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doAccountTransactionUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
|
||||
void doServerSubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doServerUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doLedgerAccountsSubcribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doLedgerAccountsUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doTransactionSubcribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
void doTransactionUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest);
|
||||
};
|
||||
Reference in New Issue
Block a user