mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -70,11 +70,11 @@ void Application::run()
|
||||
if (!theConfig.DEBUG_LOGFILE.empty())
|
||||
Log::setLogFile(theConfig.DEBUG_LOGFILE);
|
||||
|
||||
mSNTPClient.init(theConfig.SNTP_SERVERS);
|
||||
|
||||
boost::thread auxThread(boost::bind(&boost::asio::io_service::run, &mAuxService));
|
||||
auxThread.detach();
|
||||
|
||||
mSNTPClient.init(theConfig.SNTP_SERVERS);
|
||||
|
||||
//
|
||||
// Construct databases.
|
||||
//
|
||||
|
||||
@@ -21,7 +21,9 @@ bool HashedObjectStore::store(HashedObjectType type, uint32 index,
|
||||
if (!theApp->getHashNodeDB()) return true;
|
||||
if (mCache.touch(hash))
|
||||
{
|
||||
#ifdef HS_DEBUG
|
||||
Log(lsTRACE) << "HOS: " << hash.GetHex() << " store: incache";
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mL
|
||||
}
|
||||
|
||||
|
||||
Ledger::Ledger(bool dummy, Ledger& prevLedger) :
|
||||
Ledger::Ledger(bool /* dummy */, Ledger& prevLedger) :
|
||||
mTotCoins(prevLedger.mTotCoins), mLedgerSeq(prevLedger.mLedgerSeq + 1),
|
||||
mParentCloseTime(prevLedger.mCloseTime), mCloseResolution(prevLedger.mCloseResolution),
|
||||
mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "HashPrefixes.h"
|
||||
|
||||
// #define LA_DEBUG
|
||||
#define LEDGER_ACQUIRE_TIMEOUT 2
|
||||
#define LEDGER_ACQUIRE_TIMEOUT 1
|
||||
#define TRUST_NETWORK
|
||||
|
||||
PeerSet::PeerSet(const uint256& hash, int interval) : mHash(hash), mTimerInterval(interval), mTimeouts(0),
|
||||
|
||||
@@ -26,7 +26,10 @@ TransactionAcquire::TransactionAcquire(const uint256& hash) : PeerSet(hash, 1),
|
||||
void TransactionAcquire::done()
|
||||
{
|
||||
if (mFailed)
|
||||
{
|
||||
Log(lsWARNING) << "Failed to acqiure TXs " << mHash.GetHex();
|
||||
theApp->getOPs().mapComplete(mHash, SHAMap::pointer());
|
||||
}
|
||||
else
|
||||
theApp->getOPs().mapComplete(mHash, mMap);
|
||||
}
|
||||
@@ -48,7 +51,7 @@ void TransactionAcquire::trigger(Peer::pointer peer, bool timer)
|
||||
*(tmGL.add_nodeids()) = SHAMapNode().getRawString();
|
||||
sendRequest(tmGL, peer);
|
||||
}
|
||||
if (mHaveRoot)
|
||||
else
|
||||
{
|
||||
std::vector<SHAMapNode> nodeIDs; std::vector<uint256> nodeHashes;
|
||||
ConsensusTransSetSF sf;
|
||||
@@ -67,10 +70,7 @@ void TransactionAcquire::trigger(Peer::pointer peer, bool timer)
|
||||
tmGL.set_itype(newcoin::liTS_CANDIDATE);
|
||||
for (std::vector<SHAMapNode>::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it)
|
||||
*(tmGL.add_nodeids()) = it->getRawString();
|
||||
if (peer)
|
||||
sendRequest(tmGL, peer);
|
||||
else
|
||||
sendRequest(tmGL);
|
||||
sendRequest(tmGL, peer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -224,7 +224,7 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::pointer pre
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(lsINFO) << "Entering consensus process, proposing";
|
||||
Log(lsINFO) << "Entering consensus process, watching";
|
||||
mHaveCorrectLCL = true;
|
||||
mProposing = mValidating = false;
|
||||
}
|
||||
@@ -249,6 +249,9 @@ void LedgerConsensus::checkLCL()
|
||||
mPrevLedgerHash = netLgr;
|
||||
mAcquiringLedger = theApp->getMasterLedgerAcquire().findCreate(mPrevLedgerHash);
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
mHaveCorrectLCL = false;
|
||||
mProposing = false;
|
||||
mValidating = false;
|
||||
bool found = false;
|
||||
for (std::vector<Peer::pointer>::const_iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
|
||||
if ((*it)->hasLedger(mPrevLedgerHash))
|
||||
@@ -405,7 +408,12 @@ void LedgerConsensus::statePreClose()
|
||||
int proposersClosed = mPeerPositions.size();
|
||||
|
||||
// This ledger is open. This computes how long since the last ledger closed
|
||||
int sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - theApp->getOPs().getLastCloseNetTime());
|
||||
int lastCloseTime;
|
||||
if (!anyTransactions && mPreviousLedger->getCloseAgree())
|
||||
lastCloseTime = mPreviousLedger->getCloseTimeNC();
|
||||
else
|
||||
lastCloseTime = theApp->getOPs().getLastCloseNetTime();
|
||||
int sinceClose = 1000 * (theApp->getOPs().getCloseTimeNC() - lastCloseTime);
|
||||
|
||||
if (sinceClose >= ContinuousLedgerTiming::shouldClose(anyTransactions, mPreviousProposers, proposersClosed,
|
||||
mPreviousMSeconds, sinceClose))
|
||||
@@ -418,6 +426,8 @@ void LedgerConsensus::statePreClose()
|
||||
statusChange(newcoin::neCLOSING_LEDGER, *mPreviousLedger);
|
||||
takeInitialPosition(*theApp->getMasterLedger().closeLedger());
|
||||
}
|
||||
else
|
||||
checkLCL();
|
||||
}
|
||||
|
||||
void LedgerConsensus::stateEstablish()
|
||||
@@ -441,9 +451,7 @@ void LedgerConsensus::stateEstablish()
|
||||
void LedgerConsensus::stateFinished()
|
||||
{ // we are processing the finished ledger
|
||||
// logic of calculating next ledger advances us out of this state
|
||||
|
||||
// CHECKME: Should we count proposers that didn't converge to our consensus set?
|
||||
theApp->getOPs().newLCL(mPeerPositions.size(), mCurrentMSeconds, mNewLedgerHash);
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
void LedgerConsensus::stateAccepted()
|
||||
@@ -544,6 +552,8 @@ void LedgerConsensus::updateOurPositions()
|
||||
++thresh;
|
||||
}
|
||||
thresh = thresh * neededWeight / 100;
|
||||
if (thresh == 0)
|
||||
thresh = 1;
|
||||
|
||||
for (std::map<uint32, int>::iterator it = closeTimes.begin(), end = closeTimes.end(); it != end; ++it)
|
||||
{
|
||||
@@ -553,6 +563,7 @@ void LedgerConsensus::updateOurPositions()
|
||||
Log(lsINFO) << "Close time consensus reached: " << closeTime;
|
||||
mHaveCloseTimeConsensus = true;
|
||||
closeTime = it->first;
|
||||
thresh = it->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,6 +778,7 @@ void LedgerConsensus::beginAccept()
|
||||
return;
|
||||
}
|
||||
|
||||
theApp->getOPs().newLCL(mPeerPositions.size(), mCurrentMSeconds, mNewLedgerHash);
|
||||
boost::thread thread(boost::bind(&LedgerConsensus::Saccept, shared_from_this(), consensusSet));
|
||||
thread.detach();
|
||||
}
|
||||
@@ -876,7 +888,8 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
if (mHaveCorrectLCL)
|
||||
{
|
||||
Log(lsINFO) << "CNF tx " << mOurPosition->getCurrentHash().GetHex() << ", close " << closeTime;
|
||||
Log(lsINFO) << "CNF oldLCL " << mPrevLedgerHash.GetHex();
|
||||
Log(lsINFO) << "CNF mode " << theApp->getOPs().getOperatingMode()
|
||||
<< ", oldLCL " << mPrevLedgerHash.GetHex();
|
||||
}
|
||||
|
||||
Ledger::pointer newLCL = boost::make_shared<Ledger>(false, boost::ref(*mPreviousLedger));
|
||||
@@ -903,12 +916,12 @@ void LedgerConsensus::accept(SHAMap::pointer set)
|
||||
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
|
||||
(newLCLHash, newLCL->getCloseTimeNC(), mValSeed, mProposing);
|
||||
v->setTrusted();
|
||||
Log(lsINFO) << "CNF Val " << newLCLHash.GetHex();
|
||||
theApp->getValidations().addValidation(v);
|
||||
std::vector<unsigned char> validation = v->getSigned();
|
||||
newcoin::TMValidation val;
|
||||
val.set_validation(&validation[0], validation.size());
|
||||
theApp->getConnectionPool().relayMessage(NULL, boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
|
||||
Log(lsINFO) << "CNF Val " << newLCLHash.GetHex();
|
||||
}
|
||||
else
|
||||
Log(lsINFO) << "CNF newLCL " << newLCLHash.GetHex();
|
||||
|
||||
@@ -17,13 +17,13 @@ int ContinuousLedgerTiming::shouldClose(
|
||||
int previousProposers, // proposers in the last closing
|
||||
int proposersClosed, // proposers who have currently closed this ledgers
|
||||
int previousMSeconds, // seconds the previous ledger took to reach consensus
|
||||
int currentMSeconds) // seconds since the previous ledger closed
|
||||
int currentMSeconds) // seconds since the previous ledger closed
|
||||
{
|
||||
if ((previousMSeconds < -1000) || (previousMSeconds > 600000) ||
|
||||
(currentMSeconds < -1000) || (currentMSeconds > 600000))
|
||||
{
|
||||
Log(lsFATAL) <<
|
||||
boost::str(boost::format("CLC::shouldClose range error Trans=%s, Prop: %d/%d, Secs: %d (last:%d)")
|
||||
Log(lsWARNING) <<
|
||||
boost::str(boost::format("CLC::shouldClose range Trans=%s, Prop: %d/%d, Secs: %d (last:%d)")
|
||||
% (anyTransactions ? "yes" : "no") % previousProposers % proposersClosed
|
||||
% currentMSeconds % previousMSeconds);
|
||||
return currentMSeconds;
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
// The number of seconds a ledger may remain idle before closing
|
||||
# define LEDGER_IDLE_INTERVAL 15
|
||||
|
||||
// The number of seconds a validation remains current
|
||||
# define LEDGER_MAX_INTERVAL (LEDGER_IDLE_INTERVAL * 4)
|
||||
// The number of seconds a validation remains current after its ledger's close time
|
||||
// This is a safety to protect against very old validations and the time it takes to adjust
|
||||
// the close time accuracy window
|
||||
# define LEDGER_VAL_INTERVAL 600
|
||||
|
||||
// The number of seconds before a close time that we consider a validation acceptable
|
||||
// This protects against extreme clock errors
|
||||
# define LEDGER_EARLY_INTERVAL 240
|
||||
|
||||
// The number of milliseconds we wait minimum to ensure participation
|
||||
# define LEDGER_MIN_CONSENSUS 2000
|
||||
|
||||
@@ -322,8 +322,11 @@ public:
|
||||
{
|
||||
if (trustedValidations > v.trustedValidations) return true;
|
||||
if (trustedValidations < v.trustedValidations) return false;
|
||||
if (nodesUsing > v.nodesUsing) return true;
|
||||
if (nodesUsing < v.nodesUsing) return false;
|
||||
if (trustedValidations == 0)
|
||||
{
|
||||
if (nodesUsing > v.nodesUsing) return true;
|
||||
if (nodesUsing < v.nodesUsing) return false;
|
||||
}
|
||||
return highNode > v.highNode;
|
||||
}
|
||||
};
|
||||
@@ -332,6 +335,7 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
{ // Network state machine
|
||||
if (result == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
setStateTimer();
|
||||
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
|
||||
@@ -344,7 +348,6 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
Log(lsWARNING) << "Node count (" << peerList.size() <<
|
||||
") has fallen below quorum (" << theConfig.NETWORK_QUORUM << ").";
|
||||
}
|
||||
setStateTimer();
|
||||
return;
|
||||
}
|
||||
if (mMode == omDISCONNECTED)
|
||||
@@ -356,7 +359,6 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
if (mConsensus)
|
||||
{
|
||||
mConsensus->timerEntry();
|
||||
setStateTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -383,15 +385,13 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
// check if the ledger is good enough to go to omFULL
|
||||
// Note: Do not go to omFULL if we don't have the previous ledger
|
||||
// check if the ledger is bad enough to go to omCONNECTED -- TODO
|
||||
if (theApp->getOPs().getNetworkTimeNC() <
|
||||
(theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC() + 4))
|
||||
if (theApp->getOPs().getNetworkTimeNC() < theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC())
|
||||
setMode(omFULL);
|
||||
else
|
||||
Log(lsINFO) << "Will try to go to FULL in consensus window";
|
||||
}
|
||||
|
||||
if (mMode == omFULL)
|
||||
{
|
||||
// WRITEME
|
||||
// check if the ledger is bad enough to go to omTRACKING
|
||||
}
|
||||
|
||||
@@ -399,7 +399,6 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
beginConsensus(networkClosed, theApp->getMasterLedger().getCurrentLedger());
|
||||
if (mConsensus)
|
||||
mConsensus->timerEntry();
|
||||
setStateTimer();
|
||||
}
|
||||
|
||||
bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerList, uint256& networkClosed)
|
||||
@@ -458,9 +457,10 @@ bool NetworkOPs::checkLastClosedLedger(const std::vector<Peer::pointer>& peerLis
|
||||
for (boost::unordered_map<uint256, ValidationCount>::iterator it = ledgers.begin(), end = ledgers.end();
|
||||
it != end; ++it)
|
||||
{
|
||||
Log(lsTRACE) << "L: " << it->first.GetHex() <<
|
||||
" t=" << it->second.trustedValidations << ", n=" << it->second.nodesUsing;
|
||||
if ((it->second > bestVC) && !theApp->getValidations().isDeadLedger(it->first))
|
||||
bool isDead = theApp->getValidations().isDeadLedger(it->first);
|
||||
Log(lsTRACE) << "L: " << it->first.GetHex() << ((isDead) ? " dead" : " live") <<
|
||||
" t=" << it->second.trustedValidations << ", n=" << it->second.nodesUsing;
|
||||
if ((it->second > bestVC) && !isDead)
|
||||
{
|
||||
bestVC = it->second;
|
||||
closedLedger = it->first;
|
||||
@@ -632,20 +632,23 @@ bool NetworkOPs::recvPropose(uint32 proposeSeq, const uint256& proposeHash, uint
|
||||
|
||||
SHAMap::pointer NetworkOPs::getTXMap(const uint256& hash)
|
||||
{
|
||||
if (!mConsensus) return SHAMap::pointer();
|
||||
if (!mConsensus)
|
||||
return SHAMap::pointer();
|
||||
return mConsensus->getTransactionTree(hash, false);
|
||||
}
|
||||
|
||||
bool NetworkOPs::gotTXData(boost::shared_ptr<Peer> peer, const uint256& hash,
|
||||
const std::list<SHAMapNode>& nodeIDs, const std::list< std::vector<unsigned char> >& nodeData)
|
||||
{
|
||||
if (!mConsensus) return false;
|
||||
if (!mConsensus)
|
||||
return false;
|
||||
return mConsensus->peerGaveNodes(peer, hash, nodeIDs, nodeData);
|
||||
}
|
||||
|
||||
bool NetworkOPs::hasTXSet(boost::shared_ptr<Peer> peer, const uint256& set, newcoin::TxSetStatus status)
|
||||
{
|
||||
if (!mConsensus) return false;
|
||||
if (!mConsensus)
|
||||
return false;
|
||||
return mConsensus->peerHasSet(peer, set, status);
|
||||
}
|
||||
|
||||
@@ -676,10 +679,14 @@ void NetworkOPs::setMode(OperatingMode om)
|
||||
if ((om >= omCONNECTED) && (mMode == omDISCONNECTED))
|
||||
mConnectTime = boost::posix_time::second_clock::universal_time();
|
||||
Log l((om < mMode) ? lsWARNING : lsINFO);
|
||||
if (om == omDISCONNECTED) l << "STATE->Disonnected";
|
||||
else if (om == omCONNECTED) l << "STATE->Connected";
|
||||
else if (om == omTRACKING) l << "STATE->Tracking";
|
||||
else l << "STATE->Full";
|
||||
if (om == omDISCONNECTED)
|
||||
l << "STATE->Disonnected";
|
||||
else if (om == omCONNECTED)
|
||||
l << "STATE->Connected";
|
||||
else if (om == omTRACKING)
|
||||
l << "STATE->Tracking";
|
||||
else
|
||||
l << "STATE->Full";
|
||||
mMode = om;
|
||||
}
|
||||
|
||||
|
||||
@@ -928,7 +928,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
{
|
||||
SHAMap::pointer map;
|
||||
newcoin::TMLedgerData reply;
|
||||
bool fatLeaves = true;
|
||||
bool fatLeaves = true, fatRoot = false;
|
||||
|
||||
if (packet.itype() == newcoin::liTS_CANDIDATE)
|
||||
{ // Request is for a transaction candidate set
|
||||
@@ -952,6 +952,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
reply.set_ledgerhash(txHash.begin(), txHash.size());
|
||||
reply.set_type(newcoin::liTS_CANDIDATE);
|
||||
fatLeaves = false; // We'll already have most transactions
|
||||
fatRoot = true; // Save a pass
|
||||
}
|
||||
else
|
||||
{ // Figure out what ledger they want
|
||||
@@ -1057,7 +1058,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
}
|
||||
std::vector<SHAMapNode> nodeIDs;
|
||||
std::list< std::vector<unsigned char> > rawNodes;
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes, fatLeaves))
|
||||
if(map->getNodeFat(mn, nodeIDs, rawNodes, fatRoot, fatLeaves))
|
||||
{
|
||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||
std::list< std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||
@@ -1074,7 +1075,8 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (packet.has_requestcookie()) reply.set_requestcookie(packet.requestcookie());
|
||||
if (packet.has_requestcookie())
|
||||
reply.set_requestcookie(packet.requestcookie());
|
||||
PackedMessage::pointer oPacket = boost::make_shared<PackedMessage>(reply, newcoin::mtLEDGER_DATA);
|
||||
sendPacket(oPacket);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ Json::Value RPCServer::RPCError(int iError)
|
||||
{ rpcBAD_SEED, "badSeed", "Disallowed seed." },
|
||||
{ rpcDST_ACT_MALFORMED, "dstActMalformed", "Destination account is malformed." },
|
||||
{ rpcDST_AMT_MALFORMED, "dstAmtMalformed", "Destination amount/currency is malformed." },
|
||||
{ rpcDST_ACT_MISSING, "dstActMissing", "Destination account does not exists." },
|
||||
{ rpcFAIL_GEN_DECRPYT, "failGenDecrypt", "Failed to decrypt generator." },
|
||||
{ rpcGETS_ACT_MALFORMED, "getsActMalformed", "Gets account malformed." },
|
||||
{ rpcGETS_AMT_MALFORMED, "getsAmtMalformed", "Gets ammount malformed." },
|
||||
@@ -70,8 +71,8 @@ Json::Value RPCServer::RPCError(int iError)
|
||||
{ rpcPORT_MALFORMED, "portMalformed", "Port is malformed." },
|
||||
{ rpcPUBLIC_MALFORMED, "publicMalformed", "Public key is malformed." },
|
||||
{ rpcSRC_ACT_MALFORMED, "srcActMalformed", "Source account is malformed." },
|
||||
{ rpcSRC_ACT_MISSING, "srcActMissing", "Source account does not exist." },
|
||||
{ rpcSRC_AMT_MALFORMED, "srcAmtMalformed", "Source amount/currency is malformed." },
|
||||
{ rpcSRC_MISSING, "srcMissing", "Source account does not exist." },
|
||||
{ rpcSRC_UNCLAIMED, "srcUnclaimed", "Source account is not claimed." },
|
||||
{ rpcSUCCESS, "success", "Success." },
|
||||
{ rpcTXN_NOT_FOUND, "txnNotFound", "Transaction not found." },
|
||||
@@ -279,7 +280,7 @@ Json::Value RPCServer::authorize(const uint256& uLedger,
|
||||
asSrc = mNetOps->getAccountState(uLedger, naSrcAccountID);
|
||||
if (!asSrc)
|
||||
{
|
||||
return RPCError(rpcSRC_MISSING);
|
||||
return RPCError(rpcSRC_ACT_MISSING);
|
||||
}
|
||||
|
||||
NewcoinAddress naMasterGenerator;
|
||||
@@ -546,7 +547,7 @@ Json::Value RPCServer::doAccountInfo(const Json::Value ¶ms)
|
||||
{
|
||||
std::string strIdent = params[0u].asString();
|
||||
bool bIndex;
|
||||
int iIndex = 2 == params.size()? lexical_cast_s<int>(params[1u].asString()) : 0;
|
||||
int iIndex = 2 == params.size() ? lexical_cast_s<int>(params[1u].asString()) : 0;
|
||||
NewcoinAddress naAccount;
|
||||
|
||||
Json::Value ret;
|
||||
@@ -1385,6 +1386,239 @@ Json::Value RPCServer::doRippleLineSet(const Json::Value& params)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ripple <regular_seed> <paying_account>
|
||||
// <source_max> <source_currency> <source_issuerID> [noredeem] [noissue]
|
||||
// <path>+
|
||||
// full|partial <dest_account> <dest_amount> <dest_currency> <dest_issuerID>
|
||||
//
|
||||
// path:
|
||||
// path <path_element>+
|
||||
//
|
||||
// path_element:
|
||||
// account <accountID> [<currency>] [<issuerID>] [noredeem] [noissue]
|
||||
// offer <currency> [<issuerID>]
|
||||
Json::Value RPCServer::doRipple(const Json::Value ¶ms)
|
||||
{
|
||||
NewcoinAddress naSeed;
|
||||
STAmount saSrcAmountMax;
|
||||
uint160 uSrcCurrencyID;
|
||||
NewcoinAddress naSrcAccountID;
|
||||
bool bSrcRedeem = true;
|
||||
bool bSrcIssue = true;
|
||||
bool bPartial;
|
||||
bool bFull;
|
||||
NewcoinAddress naDstAccountID;
|
||||
STAmount saDstAmount;
|
||||
uint160 uDstCurrencyID;
|
||||
NewcoinAddress naDstIssuerID;
|
||||
|
||||
std::vector<paymentNode> vpnPath;
|
||||
STPathSet spsPaths;
|
||||
|
||||
if (!naSeed.setSeedGeneric(params[0u].asString())) // <regular_seed>
|
||||
{
|
||||
return RPCError(rpcBAD_SEED);
|
||||
}
|
||||
else if (!naSrcAccountID.setAccountID(params[1u].asString())) // <paying_account>
|
||||
{
|
||||
return RPCError(rpcSRC_ACT_MALFORMED);
|
||||
}
|
||||
// <source_max> <source_currency> <source_issuerID>
|
||||
else if (!saSrcAmountMax.setFullValue(params[2u].asString(), params[3u].asString(), params[4u].asString()))
|
||||
{
|
||||
return RPCError(rpcSRC_AMT_MALFORMED);
|
||||
}
|
||||
|
||||
int iArg = 5;
|
||||
|
||||
if (params[iArg].asString() == "noredeem") // [noredeem]
|
||||
{
|
||||
++iArg;
|
||||
bSrcRedeem = false;
|
||||
}
|
||||
|
||||
if (params[iArg].asString() == "noissue") // [noissue]
|
||||
{
|
||||
++iArg;
|
||||
bSrcIssue = false;
|
||||
}
|
||||
|
||||
// XXX bSrcRedeem & bSrcIssue not used.
|
||||
STPath spPath;
|
||||
|
||||
while (params.size() != iArg && params[iArg].asString() == "path") // path
|
||||
{
|
||||
Log(lsINFO) << "Path>";
|
||||
++iArg;
|
||||
|
||||
while (params.size() != iArg
|
||||
&& (params[iArg].asString() == "offer" || params[iArg].asString() == "account"))
|
||||
{
|
||||
if (params.size() >= iArg + 3 && params[iArg].asString() == "offer") // offer
|
||||
{
|
||||
Log(lsINFO) << "Offer>";
|
||||
uint160 uCurrencyID;
|
||||
NewcoinAddress naIssuerID;
|
||||
|
||||
++iArg;
|
||||
|
||||
if (!STAmount::currencyFromString(uCurrencyID, params[iArg++].asString())) // <currency>
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
else if (naIssuerID.setAccountID(params[iArg].asString())) // [<issuerID>]
|
||||
{
|
||||
++iArg;
|
||||
}
|
||||
|
||||
spPath.addElement(STPathElement(
|
||||
uint160(0),
|
||||
uCurrencyID,
|
||||
naIssuerID.isValid() ? naIssuerID.getAccountID() : uint160(0)));
|
||||
}
|
||||
else if (params.size() >= iArg + 2 && params[iArg].asString() == "account") // account
|
||||
{
|
||||
Log(lsINFO) << "Account>";
|
||||
NewcoinAddress naAccountID;
|
||||
uint160 uCurrencyID;
|
||||
NewcoinAddress naIssuerID;
|
||||
bool bRedeem = true;
|
||||
bool bIssue = true;
|
||||
|
||||
++iArg;
|
||||
|
||||
if (!naAccountID.setAccountID(params[iArg++].asString())) // <accountID>
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
|
||||
if (params.size() != iArg && STAmount::currencyFromString(uCurrencyID, params[iArg].asString())) // [<currency>]
|
||||
{
|
||||
++iArg;
|
||||
}
|
||||
|
||||
if (params.size() != iArg && naIssuerID.setAccountID(params[iArg].asString())) // [<issuerID>]
|
||||
{
|
||||
++iArg;
|
||||
}
|
||||
|
||||
if (params.size() != iArg && params[iArg].asString() == "noredeem") // [noredeem]
|
||||
{
|
||||
++iArg;
|
||||
bRedeem = false;
|
||||
}
|
||||
|
||||
if (params.size() != iArg && params[iArg].asString() == "noissue") // [noissue]
|
||||
{
|
||||
++iArg;
|
||||
bIssue = false;
|
||||
}
|
||||
|
||||
spPath.addElement(STPathElement(
|
||||
naAccountID.getAccountID(),
|
||||
uCurrencyID,
|
||||
naIssuerID.isValid() ? naIssuerID.getAccountID() : uint160(0),
|
||||
bRedeem,
|
||||
bIssue));
|
||||
}
|
||||
else
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
}
|
||||
|
||||
if (spPath.isEmpty())
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
spsPaths.addPath(spPath);
|
||||
spPath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// full|partial
|
||||
bPartial = params.size() != iArg ? params[iArg].asString() == "partial" : false;
|
||||
bFull = params.size() != iArg ? params[iArg].asString() == "full" : false;
|
||||
|
||||
if (!bPartial && !bFull)
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iArg;
|
||||
}
|
||||
|
||||
if (params.size() != iArg && !naDstAccountID.setAccountID(params[iArg++].asString())) // <dest_account>
|
||||
{
|
||||
return RPCError(rpcDST_ACT_MALFORMED);
|
||||
}
|
||||
// <dest_amount> <dest_currency> <dest_issuerID>
|
||||
else if (params.size() != iArg + 3 || !saDstAmount.setFullValue(params[iArg].asString(), params[iArg+1].asString(), params[iArg+2].asString()))
|
||||
{
|
||||
Log(lsINFO) << "params.size(): " << params.size();
|
||||
Log(lsINFO) << " iArg: " << iArg;
|
||||
Log(lsINFO) << " Amount: " << params[iArg].asString();
|
||||
Log(lsINFO) << "Currency: " << params[iArg+1].asString();
|
||||
Log(lsINFO) << " Issuer: " << params[iArg+2].asString();
|
||||
|
||||
return RPCError(rpcDST_AMT_MALFORMED);
|
||||
}
|
||||
|
||||
uint256 uLedger = mNetOps->getCurrentLedger();
|
||||
AccountState::pointer asDst = mNetOps->getAccountState(uLedger, naDstAccountID);
|
||||
STAmount saFee = theConfig.FEE_DEFAULT;
|
||||
|
||||
NewcoinAddress naVerifyGenerator;
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPrivate;
|
||||
AccountState::pointer asSrc;
|
||||
STAmount saSrcBalance;
|
||||
Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate,
|
||||
saSrcBalance, saFee, asSrc, naVerifyGenerator);
|
||||
|
||||
if (!obj.empty())
|
||||
return obj;
|
||||
|
||||
// YYY Could do some checking: source has funds or credit, dst exists and has sufficent credit limit.
|
||||
// YYY Currency from same source or loops not allowed.
|
||||
// YYY Limit paths length and count.
|
||||
if (!asDst)
|
||||
{
|
||||
return RPCError(rpcDST_ACT_MISSING);
|
||||
}
|
||||
|
||||
Transaction::pointer trans = Transaction::sharedPayment(
|
||||
naAccountPublic, naAccountPrivate,
|
||||
naSrcAccountID,
|
||||
asSrc->getSeq(),
|
||||
saFee,
|
||||
0, // YYY No source tag
|
||||
naDstAccountID,
|
||||
saDstAmount,
|
||||
saSrcAmountMax,
|
||||
spsPaths);
|
||||
|
||||
trans = mNetOps->submitTransaction(trans);
|
||||
|
||||
obj["transaction"] = trans->getSTransaction()->getJson(0);
|
||||
obj["status"] = trans->getStatus();
|
||||
obj["seed"] = naSeed.humanSeed();
|
||||
obj["fee"] = saFee.getText();
|
||||
obj["srcAccountID"] = naSrcAccountID.humanAccountID();
|
||||
obj["dstAccountID"] = naDstAccountID.humanAccountID();
|
||||
obj["srcAmountMax"] = saSrcAmountMax.getText();
|
||||
obj["srcISO"] = saSrcAmountMax.getHumanCurrency();
|
||||
obj["dstAmount"] = saDstAmount.getText();
|
||||
obj["dstISO"] = saDstAmount.getHumanCurrency();
|
||||
obj["paths"] = spsPaths.getText();
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
// ripple_lines_get <account>|<nickname>|<account_public_key> [<index>]
|
||||
Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms)
|
||||
{
|
||||
@@ -1393,7 +1627,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms)
|
||||
|
||||
std::string strIdent = params[0u].asString();
|
||||
bool bIndex;
|
||||
int iIndex = 2 == params.size()? lexical_cast_s<int>(params[1u].asString()) : 0;
|
||||
int iIndex = 2 == params.size() ? lexical_cast_s<int>(params[1u].asString()) : 0;
|
||||
|
||||
NewcoinAddress naAccount;
|
||||
|
||||
@@ -1501,11 +1735,10 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
NewcoinAddress naSeed;
|
||||
NewcoinAddress naSrcAccountID;
|
||||
NewcoinAddress naDstAccountID;
|
||||
STAmount saSrcAmount;
|
||||
STAmount saSrcAmountMax;
|
||||
STAmount saDstAmount;
|
||||
std::string sSrcCurrency;
|
||||
std::string sDstCurrency;
|
||||
uint256 uLedger = mNetOps->getCurrentLedger();
|
||||
|
||||
if (params.size() >= 5)
|
||||
sDstCurrency = params[4u].asString();
|
||||
@@ -1529,12 +1762,13 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
{
|
||||
return RPCError(rpcDST_AMT_MALFORMED);
|
||||
}
|
||||
else if (params.size() >= 6 && !saSrcAmount.setFullValue(params[5u].asString(), sSrcCurrency))
|
||||
else if (params.size() >= 6 && !saSrcAmountMax.setFullValue(params[5u].asString(), sSrcCurrency))
|
||||
{
|
||||
return RPCError(rpcSRC_AMT_MALFORMED);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint256 uLedger = mNetOps->getCurrentLedger();
|
||||
AccountState::pointer asDst = mNetOps->getAccountState(uLedger, naDstAccountID);
|
||||
bool bCreate = !asDst;
|
||||
STAmount saFee = bCreate ? theConfig.FEE_ACCOUNT_CREATE : theConfig.FEE_DEFAULT;
|
||||
@@ -1551,10 +1785,10 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
return obj;
|
||||
|
||||
if (params.size() < 6)
|
||||
saSrcAmount = saDstAmount;
|
||||
saSrcAmountMax = saDstAmount;
|
||||
|
||||
// Do a few simple checks.
|
||||
if (!saSrcAmount.isNative())
|
||||
if (!saSrcAmountMax.isNative())
|
||||
{
|
||||
Log(lsINFO) << "doSend: Ripple";
|
||||
|
||||
@@ -1567,11 +1801,11 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
|
||||
return RPCError(rpcINSUF_FUNDS);
|
||||
}
|
||||
else if (saDstAmount.isNative() && saSrcAmount < saDstAmount)
|
||||
else if (saDstAmount.isNative() && saSrcAmountMax < saDstAmount)
|
||||
{
|
||||
// Not enough native currency.
|
||||
|
||||
Log(lsINFO) << "doSend: Insufficient funds: src=" << saSrcAmount.getText() << " dst=" << saDstAmount.getText();
|
||||
Log(lsINFO) << "doSend: Insufficient funds: src=" << saSrcAmountMax.getText() << " dst=" << saDstAmount.getText();
|
||||
|
||||
return RPCError(rpcINSUF_FUNDS);
|
||||
}
|
||||
@@ -1582,7 +1816,7 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
if (asDst) {
|
||||
// Destination exists, ordinary send.
|
||||
|
||||
STPathSet spPaths;
|
||||
STPathSet spsPaths;
|
||||
|
||||
trans = Transaction::sharedPayment(
|
||||
naAccountPublic, naAccountPrivate,
|
||||
@@ -1592,8 +1826,8 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
0, // YYY No source tag
|
||||
naDstAccountID,
|
||||
saDstAmount,
|
||||
saSrcAmount,
|
||||
spPaths);
|
||||
saSrcAmountMax,
|
||||
spsPaths);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1618,8 +1852,8 @@ Json::Value RPCServer::doSend(const Json::Value& params)
|
||||
obj["create"] = bCreate;
|
||||
obj["srcAccountID"] = naSrcAccountID.humanAccountID();
|
||||
obj["dstAccountID"] = naDstAccountID.humanAccountID();
|
||||
obj["srcAmount"] = saSrcAmount.getText();
|
||||
obj["srcISO"] = saSrcAmount.getHumanCurrency();
|
||||
obj["srcAmountMax"] = saSrcAmountMax.getText();
|
||||
obj["srcISO"] = saSrcAmountMax.getHumanCurrency();
|
||||
obj["dstAmount"] = saDstAmount.getText();
|
||||
obj["dstISO"] = saDstAmount.getHumanCurrency();
|
||||
|
||||
@@ -2156,13 +2390,21 @@ Json::Value RPCServer::doWalletCreate(const Json::Value& params)
|
||||
return obj;
|
||||
}
|
||||
|
||||
// wallet_propose
|
||||
// wallet_propose [<passphrase>]
|
||||
// <passphrase> is only for testing. Master seeds should only be generated randomly.
|
||||
Json::Value RPCServer::doWalletPropose(const Json::Value& params)
|
||||
{
|
||||
NewcoinAddress naSeed;
|
||||
NewcoinAddress naAccount;
|
||||
|
||||
naSeed.setSeedRandom();
|
||||
if (params.empty())
|
||||
{
|
||||
naSeed.setSeedRandom();
|
||||
}
|
||||
else
|
||||
{
|
||||
naSeed = NewcoinAddress::createSeedGeneric(params[0u].asString());
|
||||
}
|
||||
|
||||
NewcoinAddress naGenerator = NewcoinAddress::createGeneratorPublic(naSeed);
|
||||
naAccount.setAccountPublic(naGenerator, 0);
|
||||
@@ -2332,7 +2574,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
{ "password_fund", &RPCServer::doPasswordFund, 2, 3, false, optCurrent },
|
||||
{ "password_set", &RPCServer::doPasswordSet, 2, 3, false, optNetwork },
|
||||
{ "peers", &RPCServer::doPeers, 0, 0, true },
|
||||
{ "ripple_lines_get", &RPCServer::doRippleLinesGet, 1, 2, false, optCurrent|optClosed },
|
||||
{ "ripple", &RPCServer::doRipple, 10, -1, false, optCurrent|optClosed },
|
||||
{ "ripple_lines_get", &RPCServer::doRippleLinesGet, 1, 2, false, optCurrent },
|
||||
{ "ripple_line_set", &RPCServer::doRippleLineSet, 4, 7, false, optCurrent },
|
||||
{ "send", &RPCServer::doSend, 3, 7, false, optCurrent },
|
||||
{ "server_info", &RPCServer::doServerInfo, 0, 0, true },
|
||||
@@ -2354,7 +2597,7 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
{ "wallet_add", &RPCServer::doWalletAdd, 3, 5, false, optCurrent },
|
||||
{ "wallet_claim", &RPCServer::doWalletClaim, 2, 4, false, optNetwork },
|
||||
{ "wallet_create", &RPCServer::doWalletCreate, 3, 4, false, optCurrent },
|
||||
{ "wallet_propose", &RPCServer::doWalletPropose, 0, 0, false, },
|
||||
{ "wallet_propose", &RPCServer::doWalletPropose, 0, 1, false, },
|
||||
{ "wallet_seed", &RPCServer::doWalletSeed, 0, 1, false, },
|
||||
|
||||
{ "login", &RPCServer::doLogin, 2, 2, true },
|
||||
@@ -2373,7 +2616,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
{
|
||||
return RPCError(rpcNO_PERMISSION);
|
||||
}
|
||||
else if (params.size() < commandsA[i].iMinParams || params.size() > commandsA[i].iMaxParams)
|
||||
else if (params.size() < commandsA[i].iMinParams
|
||||
|| (commandsA[i].iMaxParams >= 0 && params.size() > commandsA[i].iMaxParams))
|
||||
{
|
||||
return RPCError(rpcINVALID_PARAMS);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
rpcACT_MALFORMED,
|
||||
rpcBAD_SEED,
|
||||
rpcDST_ACT_MALFORMED,
|
||||
rpcDST_ACT_MISSING,
|
||||
rpcDST_AMT_MALFORMED,
|
||||
rpcGETS_ACT_MALFORMED,
|
||||
rpcGETS_AMT_MALFORMED,
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
rpcPORT_MALFORMED,
|
||||
rpcPUBLIC_MALFORMED,
|
||||
rpcSRC_ACT_MALFORMED,
|
||||
rpcSRC_ACT_MISSING,
|
||||
rpcSRC_AMT_MALFORMED,
|
||||
|
||||
// Internal error (should never happen)
|
||||
@@ -146,6 +148,7 @@ private:
|
||||
Json::Value doPasswordFund(const Json::Value& params);
|
||||
Json::Value doPasswordSet(const Json::Value& params);
|
||||
Json::Value doPeers(const Json::Value& params);
|
||||
Json::Value doRipple(const Json::Value ¶ms);
|
||||
Json::Value doRippleLinesGet(const Json::Value ¶ms);
|
||||
Json::Value doRippleLineSet(const Json::Value& params);
|
||||
Json::Value doSend(const Json::Value& params);
|
||||
|
||||
@@ -327,7 +327,7 @@ public:
|
||||
void getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint256>& hashes, int max,
|
||||
SHAMapSyncFilter* filter);
|
||||
bool getNodeFat(const SHAMapNode& node, std::vector<SHAMapNode>& nodeIDs,
|
||||
std::list<std::vector<unsigned char> >& rawNode, bool fatLeaves);
|
||||
std::list<std::vector<unsigned char> >& rawNode, bool fatRoot, bool fatLeaves);
|
||||
bool getRootNode(Serializer& s, SHANodeFormat format);
|
||||
bool addRootNode(const uint256& hash, const std::vector<unsigned char>& rootNode, SHANodeFormat format);
|
||||
bool addRootNode(const std::vector<unsigned char>& rootNode, SHANodeFormat format);
|
||||
|
||||
@@ -86,7 +86,7 @@ void SHAMap::getMissingNodes(std::vector<SHAMapNode>& nodeIDs, std::vector<uint2
|
||||
}
|
||||
|
||||
bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector<SHAMapNode>& nodeIDs,
|
||||
std::list<std::vector<unsigned char> >& rawNodes, bool fatLeaves)
|
||||
std::list<std::vector<unsigned char> >& rawNodes, bool fatRoot, bool fatLeaves)
|
||||
{ // Gets a node and some of its children
|
||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||
|
||||
@@ -102,7 +102,7 @@ bool SHAMap::getNodeFat(const SHAMapNode& wanted, std::vector<SHAMapNode>& nodeI
|
||||
node->addRaw(s, snfWIRE);
|
||||
rawNodes.push_back(s.peekData());
|
||||
|
||||
if (node->isRoot() || node->isLeaf()) // don't get a fat root, can't get a fat leaf
|
||||
if ((!fatRoot && node->isRoot()) || node->isLeaf()) // don't get a fat root, can't get a fat leaf
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
@@ -141,7 +141,8 @@ bool SHAMap::addRootNode(const std::vector<unsigned char>& rootNode, SHANodeForm
|
||||
}
|
||||
|
||||
SHAMapTreeNode::pointer node = boost::make_shared<SHAMapTreeNode>(SHAMapNode(), rootNode, 0, format);
|
||||
if (!node) return false;
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
#ifdef DEBUG
|
||||
node->dump();
|
||||
@@ -444,7 +445,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
|
||||
destination.setSynching();
|
||||
|
||||
if (!source.getNodeFat(SHAMapNode(), nodeIDs, gotNodes, (rand() % 2) == 0))
|
||||
if (!source.getNodeFat(SHAMapNode(), nodeIDs, gotNodes, (rand() % 2) == 0, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat(root) fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
@@ -481,7 +482,7 @@ BOOST_AUTO_TEST_CASE( SHAMapSync_test )
|
||||
// get as many nodes as possible based on this information
|
||||
for (nodeIDIterator = nodeIDs.begin(); nodeIDIterator != nodeIDs.end(); ++nodeIDIterator)
|
||||
{
|
||||
if (!source.getNodeFat(*nodeIDIterator, gotNodeIDs, gotNodes, (rand() % 2) == 0))
|
||||
if (!source.getNodeFat(*nodeIDIterator, gotNodeIDs, gotNodes, (rand() % 2) == 0, (rand() % 2) == 0))
|
||||
{
|
||||
Log(lsFATAL) << "GetNodeFat fails";
|
||||
BOOST_FAIL("GetNodeFat");
|
||||
|
||||
@@ -346,6 +346,12 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name)
|
||||
} while(1);
|
||||
}
|
||||
|
||||
bool STPathSet::isEquivalent(const SerializedType& t) const
|
||||
{
|
||||
const STPathSet* v = dynamic_cast<const STPathSet*>(&t);
|
||||
return v && (value == v->value);
|
||||
}
|
||||
|
||||
int STPathSet::getLength() const
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
|
||||
bool isNative() const { return mIsNative; }
|
||||
bool isZero() const { return mValue == 0; }
|
||||
bool isNonZero() const { return mValue != 0; }
|
||||
bool isNonZero() const { return mValue != 0; }
|
||||
bool isNegative() const { return mIsNegative && !isZero(); }
|
||||
bool isPositive() const { return !mIsNegative && !isZero(); }
|
||||
bool isGEZero() const { return !mIsNegative; }
|
||||
@@ -528,23 +528,31 @@ public:
|
||||
typeCurrency = 0x10, // Currency follows.
|
||||
typeIssuer = 0x20, // Issuer follows.
|
||||
typeBoundary = 0xFF, // Boundary between alternate paths.
|
||||
typeValidBits = 0x3E, // Bits that may be non-zero.
|
||||
typeValidBits = (
|
||||
typeAccount
|
||||
| typeRedeem
|
||||
| typeIssue
|
||||
| typeCurrency
|
||||
| typeIssuer
|
||||
), // Bits that may be non-zero.
|
||||
};
|
||||
|
||||
protected:
|
||||
int mType;
|
||||
uint160 mAccountID;
|
||||
uint160 mCurrency;
|
||||
uint160 mCurrencyID;
|
||||
uint160 mIssuerID;
|
||||
|
||||
public:
|
||||
STPathElement(const uint160& uAccountID, const uint160& uCurrency, const uint160& uIssuerID)
|
||||
: mAccountID(uAccountID), mCurrency(uCurrency), mIssuerID(uIssuerID)
|
||||
STPathElement(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID, bool bRedeem=false, bool bIssue=false)
|
||||
: mAccountID(uAccountID), mCurrencyID(uCurrencyID), mIssuerID(uIssuerID)
|
||||
{
|
||||
mType =
|
||||
(uAccountID.isZero() ? 0 : STPathElement::typeAccount)
|
||||
| (uCurrency.isZero() ? 0 : STPathElement::typeCurrency)
|
||||
| (uIssuerID.isZero() ? 0 : STPathElement::typeIssuer);
|
||||
| (uCurrencyID.isZero() ? 0 : STPathElement::typeCurrency)
|
||||
| (uIssuerID.isZero() ? 0 : STPathElement::typeIssuer)
|
||||
| (bRedeem ? STPathElement::typeRedeem : 0)
|
||||
| (bIssue ? STPathElement::typeIssue : 0);
|
||||
}
|
||||
|
||||
int getNodeType() const { return mType; }
|
||||
@@ -553,8 +561,11 @@ public:
|
||||
|
||||
// Nodes are either an account ID or a offer prefix. Offer prefixs denote a class of offers.
|
||||
const uint160& getAccountID() const { return mAccountID; }
|
||||
const uint160& getCurrency() const { return mCurrency; }
|
||||
const uint160& getCurrency() const { return mCurrencyID; }
|
||||
const uint160& getIssuerID() const { return mIssuerID; }
|
||||
|
||||
bool operator==(const STPathElement& t) const
|
||||
{ return mType == t.mType && mAccountID == t.mAccountID && mCurrencyID == t.mCurrencyID && mIssuerID == mIssuerID; }
|
||||
};
|
||||
|
||||
class STPath
|
||||
@@ -580,6 +591,8 @@ public:
|
||||
std::vector<STPathElement>::iterator end() { return mPath.end(); }
|
||||
std::vector<STPathElement>::const_iterator begin() const { return mPath.begin(); }
|
||||
std::vector<STPathElement>::const_iterator end() const { return mPath.end(); }
|
||||
|
||||
bool operator==(const STPath& t) const { return mPath == t.mPath; }
|
||||
};
|
||||
|
||||
inline std::vector<STPathElement>::iterator range_begin(STPath & x)
|
||||
@@ -647,6 +660,8 @@ public:
|
||||
void clear() { value.clear(); }
|
||||
void addPath(const STPath& e) { value.push_back(e); }
|
||||
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
|
||||
std::vector<STPath>::iterator begin() { return value.begin(); }
|
||||
std::vector<STPath>::iterator end() { return value.end(); }
|
||||
std::vector<STPath>::const_iterator begin() const { return value.begin(); }
|
||||
|
||||
@@ -5,16 +5,18 @@
|
||||
#include "LedgerTiming.h"
|
||||
#include "Log.h"
|
||||
|
||||
bool ValidationCollection::addValidation(SerializedValidation::pointer val)
|
||||
// #define VC_DEBUG
|
||||
|
||||
bool ValidationCollection::addValidation(SerializedValidation::pointer& val)
|
||||
{
|
||||
NewcoinAddress signer = val->getSignerPublic();
|
||||
bool isCurrent = false;
|
||||
if (theApp->getUNL().nodeInUNL(signer))
|
||||
if (theApp->getUNL().nodeInUNL(signer) || val->isTrusted())
|
||||
{
|
||||
val->setTrusted();
|
||||
uint32 now = theApp->getOPs().getCloseTimeNC();
|
||||
uint32 valClose = val->getCloseTime();
|
||||
if ((now > (valClose - 4)) && (now < (valClose + LEDGER_MAX_INTERVAL)))
|
||||
if ((now > (valClose - LEDGER_EARLY_INTERVAL)) && (now < (valClose + LEDGER_VAL_INTERVAL)))
|
||||
isCurrent = true;
|
||||
else
|
||||
Log(lsWARNING) << "Received stale validation now=" << now << ", close=" << valClose;
|
||||
@@ -51,7 +53,7 @@ bool ValidationCollection::addValidation(SerializedValidation::pointer val)
|
||||
}
|
||||
|
||||
Log(lsINFO) << "Val for " << hash.GetHex() << " from " << signer.humanNodePublic()
|
||||
<< " added " << (val->isTrusted() ? "trusted" : "UNtrusted");
|
||||
<< " added " << (val->isTrusted() ? "trusted/" : "UNtrusted/") << (isCurrent ? "current" : "stale");
|
||||
return isCurrent;
|
||||
}
|
||||
|
||||
@@ -81,8 +83,14 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
||||
if (isTrusted && currentOnly)
|
||||
{
|
||||
uint32 closeTime = vit->second->getCloseTime();
|
||||
if ((now < closeTime) || (now > (closeTime + 2 * LEDGER_MAX_INTERVAL)))
|
||||
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
|
||||
isTrusted = false;
|
||||
else
|
||||
{
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: Untrusted due to time " << ledger.GetHex();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (isTrusted)
|
||||
++trusted;
|
||||
@@ -90,6 +98,9 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
||||
++untrusted;
|
||||
}
|
||||
}
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: " << ledger.GetHex() << "t:" << trusted << " u:" << untrusted;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
|
||||
@@ -129,22 +140,27 @@ boost::unordered_map<uint256, int> ValidationCollection::getCurrentValidations()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mValidationLock);
|
||||
boost::unordered_map<uint160, ValidationPair>::iterator it = mCurrentValidations.begin();
|
||||
bool anyNew = false;
|
||||
while (it != mCurrentValidations.end())
|
||||
{
|
||||
ValidationPair& pair = it->second;
|
||||
|
||||
if (pair.oldest && (now > (pair.oldest->getCloseTime() + LEDGER_MAX_INTERVAL)))
|
||||
if (pair.oldest && (now > (pair.oldest->getCloseTime() + LEDGER_VAL_INTERVAL)))
|
||||
{
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: " << it->first.GetHex() << " removeOldestStale";
|
||||
#endif
|
||||
mStaleValidations.push_back(pair.oldest);
|
||||
pair.oldest = SerializedValidation::pointer();
|
||||
anyNew = true;
|
||||
condWrite();
|
||||
}
|
||||
if (pair.newest && (now > (pair.newest->getCloseTime() + LEDGER_MAX_INTERVAL)))
|
||||
if (pair.newest && (now > (pair.newest->getCloseTime() + LEDGER_VAL_INTERVAL)))
|
||||
{
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsINFO) << "VC: " << it->first.GetHex() << " removeNewestStale";
|
||||
#endif
|
||||
mStaleValidations.push_back(pair.newest);
|
||||
pair.newest = SerializedValidation::pointer();
|
||||
anyNew = true;
|
||||
condWrite();
|
||||
}
|
||||
if (!pair.newest && !pair.oldest)
|
||||
it = mCurrentValidations.erase(it);
|
||||
@@ -152,21 +168,23 @@ boost::unordered_map<uint256, int> ValidationCollection::getCurrentValidations()
|
||||
{
|
||||
if (pair.oldest)
|
||||
{
|
||||
Log(lsTRACE) << "OLD " << pair.oldest->getLedgerHash().GetHex() << " " <<
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsTRACE) << "VC: OLD " << pair.oldest->getLedgerHash().GetHex() << " " <<
|
||||
boost::lexical_cast<std::string>(pair.oldest->getCloseTime());
|
||||
#endif
|
||||
++ret[pair.oldest->getLedgerHash()];
|
||||
}
|
||||
if (pair.newest)
|
||||
{
|
||||
Log(lsTRACE) << "NEW " << pair.newest->getLedgerHash().GetHex() << " " <<
|
||||
#ifdef VC_DEBUG
|
||||
Log(lsTRACE) << "VC: NEW " << pair.newest->getLedgerHash().GetHex() << " " <<
|
||||
boost::lexical_cast<std::string>(pair.newest->getCloseTime());
|
||||
#endif
|
||||
++ret[pair.newest->getLedgerHash()];
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (anyNew)
|
||||
condWrite();
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -227,8 +245,7 @@ void ValidationCollection::condWrite()
|
||||
void ValidationCollection::doWrite()
|
||||
{
|
||||
static boost::format insVal("INSERT INTO LedgerValidations "
|
||||
"(LedgerHash,NodePubKey,Flags,CloseTime,Signature) VALUES "
|
||||
"('%s','%s','%u','%u',%s);");
|
||||
"(LedgerHash,NodePubKey,Flags,CloseTime,Signature) VALUES ('%s','%s','%u','%u',%s);");
|
||||
|
||||
boost::mutex::scoped_lock sl(mValidationLock);
|
||||
assert(mWriting);
|
||||
|
||||
@@ -38,7 +38,7 @@ protected:
|
||||
public:
|
||||
ValidationCollection() : mWriting(false) { ; }
|
||||
|
||||
bool addValidation(SerializedValidation::pointer);
|
||||
bool addValidation(SerializedValidation::pointer&);
|
||||
ValidationSet getValidations(const uint256& ledger);
|
||||
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void printHelp(const po::options_description& desc)
|
||||
cout << " password_fund <seed> <paying_account> [<account>]" << endl;
|
||||
cout << " password_set <master_seed> <regular_seed> [<account>]" << endl;
|
||||
cout << " peers" << endl;
|
||||
cout << " ripple ..." << endl;
|
||||
cout << " ripple_lines_get <account>|<nickname>|<account_public_key> [<index>]" << endl;
|
||||
cout << " ripple_line_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<quality_in>] [<quality_out>]" << endl;
|
||||
cout << " send <seed> <paying_account> <account_id> <amount> [<currency>] [<send_max>] [<send_currency>]" << endl;
|
||||
@@ -75,7 +76,7 @@ void printHelp(const po::options_description& desc)
|
||||
cout << " wallet_accounts <seed>" << endl;
|
||||
cout << " wallet_claim <master_seed> <regular_seed> [<source_tag>] [<account_annotation>]" << endl;
|
||||
cout << " wallet_seed [<seed>|<passphrase>|<passkey>]" << endl;
|
||||
cout << " wallet_propose" << endl;
|
||||
cout << " wallet_propose [<passphrase>]" << endl;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
||||
Reference in New Issue
Block a user