diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 0cd6e2346..36446cd67 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -20,6 +20,7 @@ #include "HashPrefixes.h" #include "Log.h" + Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount), mLedgerSeq(0), mCloseTime(0), mParentCloseTime(0), mCloseResolution(LEDGER_TIME_ACCURACY), mCloseFlags(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false), @@ -503,4 +504,196 @@ void Ledger::setCloseTime(boost::posix_time::ptime ptm) mCloseTime = iToSeconds(ptm); } +// XXX Use shared locks where possible? + +LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry) +{ + ScopedLock l(mAccountStateMap->Lock()); + bool create = false; + + if (!mAccountStateMap->hasItem(entry->getIndex())) + { + if ((parms & lepCREATE) == 0) + { + Log(lsERROR) << "WriteBack non-existent node without create"; + return lepMISSING; + } + create = true; + } + + SHAMapItem::pointer item = boost::make_shared(entry->getIndex()); + entry->add(item->peekSerializer()); + + if (create) + { + assert(!mAccountStateMap->hasItem(entry->getIndex())); + if(!mAccountStateMap->addGiveItem(item, false, false)) // FIXME: TX metadata + { + assert(false); + return lepERROR; + } + return lepCREATED; + } + + if (!mAccountStateMap->updateGiveItem(item, false, false)) // FIXME: TX metadata + { + assert(false); + return lepERROR; + } + return lepOKAY; +} + +SLE::pointer Ledger::getSLE(const uint256& uHash) +{ + SHAMapItem::pointer node = mAccountStateMap->peekItem(uHash); + if (!node) + return SLE::pointer(); + return boost::make_shared(node->peekSerializer(), node->getTag()); +} + +uint256 Ledger::getFirstLedgerIndex() +{ + SHAMapItem::pointer node = mAccountStateMap->peekFirstItem(); + return node ? node->getTag() : uint256(); +} + +uint256 Ledger::getLastLedgerIndex() +{ + SHAMapItem::pointer node = mAccountStateMap->peekLastItem(); + return node ? node->getTag() : uint256(); +} + +uint256 Ledger::getNextLedgerIndex(const uint256& uHash) +{ + SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); + return node ? node->getTag() : uint256(); +} + +uint256 Ledger::getNextLedgerIndex(const uint256& uHash, const uint256& uEnd) +{ + SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); + if ((!node) || (node->getTag() > uEnd)) + return uint256(); + return node->getTag(); +} + +uint256 Ledger::getPrevLedgerIndex(const uint256& uHash) +{ + SHAMapItem::pointer node = mAccountStateMap->peekPrevItem(uHash); + return node ? node->getTag() : uint256(); +} + +uint256 Ledger::getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin) +{ + SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); + if ((!node) || (node->getTag() < uBegin)) + return uint256(); + return node->getTag(); +} + +SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, + LedgerEntryType let ) +{ + SHAMapItem::pointer account = mAccountStateMap->peekItem(nodeID); + + if (!account) + { + if ( (parms & lepCREATE) == 0 ) + { + parms = lepMISSING; + return SLE::pointer(); + } + + parms = parms | lepCREATED | lepOKAY; + SLE::pointer sle=boost::make_shared(let); + sle->setIndex(nodeID); + + return sle; + } + + SLE::pointer sle = + boost::make_shared(account->peekSerializer(), nodeID); + + if (sle->getType() != let) + { // maybe it's a currency or something + parms = parms | lepWRONGTYPE; + return SLE::pointer(); + } + + parms = parms | lepOKAY; + + return sle; +} + +SLE::pointer Ledger::getAccountRoot(const uint160& accountID) +{ + LedgerStateParms qry = lepNONE; + + return getASNode(qry, getAccountRootIndex(accountID), ltACCOUNT_ROOT); +} + +SLE::pointer Ledger::getAccountRoot(const NewcoinAddress& naAccountID) +{ + LedgerStateParms qry = lepNONE; + + return getASNode(qry, getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT); +} + +// +// Directory +// + +SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, uNodeIndex, ltDIR_NODE); +} + +// +// Generator Map +// + +SLE::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP); +} + +// +// Nickname +// + +SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickname) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, uNickname, ltNICKNAME); +} + +// +// Offer +// + + +SLE::pointer Ledger::getOffer(LedgerStateParms& parms, const uint256& uIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, uIndex, ltOFFER); +} + +// +// Ripple State +// + +SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, uNode, ltRIPPLE_STATE); +} + + // vim:ts=4 diff --git a/src/Ledger.h b/src/Ledger.h index 3de26d5e0..90ede0848 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -265,9 +265,6 @@ public: static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency) { return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); } - // Directory of lines indexed by an account (not all lines are indexed) - static uint256 getRippleDirIndex(const uint160& uAccountID); - RippleState::pointer accessRippleState(const uint256& uNode); SLE::pointer getRippleState(LedgerStateParms& parms, const uint256& uNode); diff --git a/src/LedgerFormats.h b/src/LedgerFormats.h index 230e557c4..22ae55ebf 100644 --- a/src/LedgerFormats.h +++ b/src/LedgerFormats.h @@ -23,7 +23,6 @@ enum LedgerNameSpace spaceGenerator = 'g', spaceNickname = 'n', spaceRipple = 'r', - spaceRippleDir = 'R', spaceOffer = 'o', // Entry for an offer. spaceOwnerDir = 'O', // Directory of things owned by an account. spaceBookDir = 'B', // Directory of order books. @@ -38,10 +37,6 @@ enum LedgerSpecificFlags // ltOFFER lsfPassive = 0x00010000, - - // ltRIPPLE_STATE - lsfLowIndexed = 0x00010000, - lsfHighIndexed = 0x00020000, }; struct LedgerEntryFormat diff --git a/src/LedgerIndex.cpp b/src/LedgerIndex.cpp index 8a27e7938..b519a9e0e 100644 --- a/src/LedgerIndex.cpp +++ b/src/LedgerIndex.cpp @@ -126,16 +126,6 @@ uint256 Ledger::getOwnerDirIndex(const uint160& uAccountID) return s.getSHA512Half(); } -uint256 Ledger::getRippleDirIndex(const uint160& uAccountID) -{ - Serializer s(22); - - s.add16(spaceRippleDir); // 2 - s.add160(uAccountID); // 20 - - return s.getSHA512Half(); -} - uint256 Ledger::getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) { uint160 uAID = naA.getAccountID(); diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index bbb4b7e96..ab99f1a76 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -1,200 +1,5 @@ -#include "Ledger.h" - -#include - -#include "utils.h" -#include "Log.h" - -// XXX Use shared locks where possible? - -LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry) -{ - ScopedLock l(mAccountStateMap->Lock()); - bool create = false; - - if (!mAccountStateMap->hasItem(entry->getIndex())) - { - if ((parms & lepCREATE) == 0) - { - Log(lsERROR) << "WriteBack non-existent node without create"; - return lepMISSING; - } - create = true; - } - - SHAMapItem::pointer item = boost::make_shared(entry->getIndex()); - entry->add(item->peekSerializer()); - - if (create) - { - assert(!mAccountStateMap->hasItem(entry->getIndex())); - if(!mAccountStateMap->addGiveItem(item, false, false)) // FIXME: TX metadata - { - assert(false); - return lepERROR; - } - return lepCREATED; - } - - if (!mAccountStateMap->updateGiveItem(item, false, false)) // FIXME: TX metadata - { - assert(false); - return lepERROR; - } - return lepOKAY; -} - -SLE::pointer Ledger::getSLE(const uint256& uHash) -{ - SHAMapItem::pointer node = mAccountStateMap->peekItem(uHash); - if (!node) - return SLE::pointer(); - return boost::make_shared(node->peekSerializer(), node->getTag()); -} - -uint256 Ledger::getFirstLedgerIndex() -{ - SHAMapItem::pointer node = mAccountStateMap->peekFirstItem(); - return node ? node->getTag() : uint256(); -} - -uint256 Ledger::getLastLedgerIndex() -{ - SHAMapItem::pointer node = mAccountStateMap->peekLastItem(); - return node ? node->getTag() : uint256(); -} - -uint256 Ledger::getNextLedgerIndex(const uint256& uHash) -{ - SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); - return node ? node->getTag() : uint256(); -} - -uint256 Ledger::getNextLedgerIndex(const uint256& uHash, const uint256& uEnd) -{ - SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); - if ((!node) || (node->getTag() > uEnd)) - return uint256(); - return node->getTag(); -} - -uint256 Ledger::getPrevLedgerIndex(const uint256& uHash) -{ - SHAMapItem::pointer node = mAccountStateMap->peekPrevItem(uHash); - return node ? node->getTag() : uint256(); -} - -uint256 Ledger::getPrevLedgerIndex(const uint256& uHash, const uint256& uBegin) -{ - SHAMapItem::pointer node = mAccountStateMap->peekNextItem(uHash); - if ((!node) || (node->getTag() < uBegin)) - return uint256(); - return node->getTag(); -} - -SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, - LedgerEntryType let ) -{ - SHAMapItem::pointer account = mAccountStateMap->peekItem(nodeID); - - if (!account) - { - if ( (parms & lepCREATE) == 0 ) - { - parms = lepMISSING; - return SLE::pointer(); - } - - parms = parms | lepCREATED | lepOKAY; - SLE::pointer sle=boost::make_shared(let); - sle->setIndex(nodeID); - - return sle; - } - - SLE::pointer sle = - boost::make_shared(account->peekSerializer(), nodeID); - - if (sle->getType() != let) - { // maybe it's a currency or something - parms = parms | lepWRONGTYPE; - return SLE::pointer(); - } - - parms = parms | lepOKAY; - - return sle; -} - -SLE::pointer Ledger::getAccountRoot(const uint160& accountID) -{ - LedgerStateParms qry = lepNONE; - - return getASNode(qry, getAccountRootIndex(accountID), ltACCOUNT_ROOT); -} - -SLE::pointer Ledger::getAccountRoot(const NewcoinAddress& naAccountID) -{ - LedgerStateParms qry = lepNONE; - - return getASNode(qry, getAccountRootIndex(naAccountID.getAccountID()), ltACCOUNT_ROOT); -} - -// -// Directory -// - -SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) -{ - ScopedLock l(mAccountStateMap->Lock()); - - return getASNode(parms, uNodeIndex, ltDIR_NODE); -} - -// -// Generator Map -// - -SLE::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID) -{ - ScopedLock l(mAccountStateMap->Lock()); - - return getASNode(parms, getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP); -} - -// -// Nickname -// - -SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickname) -{ - ScopedLock l(mAccountStateMap->Lock()); - - return getASNode(parms, uNickname, ltNICKNAME); -} - -// -// Offer -// - -SLE::pointer Ledger::getOffer(LedgerStateParms& parms, const uint256& uIndex) -{ - ScopedLock l(mAccountStateMap->Lock()); - return getASNode(parms, uIndex, ltOFFER); -} - -// -// Ripple State -// - -SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode) -{ - ScopedLock l(mAccountStateMap->Lock()); - - return getASNode(parms, uNode, ltRIPPLE_STATE); -} // vim:ts=4 diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 35ae4c406..a0e781142 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -254,7 +254,7 @@ Json::Value NetworkOPs::getOwnerInfo(const uint256& uLedger, const NewcoinAddres Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const NewcoinAddress& naAccount) { - Json::Value jvObjects(Json::arrayValue); + Json::Value jvObjects(Json::objectValue); uint256 uRootIndex = lpLedger->getOwnerDirIndex(naAccount.getAccountID()); @@ -267,15 +267,37 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const NewcoinAddr do { - STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); + STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); const std::vector& vuiIndexes = svIndexes.peekValue(); BOOST_FOREACH(const uint256& uDirEntry, vuiIndexes) { - LedgerStateParms lspOffer = lepNONE; - SLE::pointer sleOffer = lpLedger->getOffer(lspOffer, uDirEntry); + SLE::pointer sleCur = lpLedger->getSLE(uDirEntry); - jvObjects.append(sleOffer->getJson(0)); + switch (sleCur->getType()) + { + case ltOFFER: + if (!jvObjects.isMember("offers")) + jvObjects["offers"] = Json::Value(Json::arrayValue); + + jvObjects["offers"].append(sleCur->getJson(0)); + break; + + case ltRIPPLE_STATE: + if (!jvObjects.isMember("ripple_lines")) + jvObjects["ripple_lines"] = Json::Value(Json::arrayValue); + + jvObjects["ripple_lines"].append(sleCur->getJson(0)); + break; + + case ltACCOUNT_ROOT: + case ltDIR_NODE: + case ltGENERATOR_MAP: + case ltNICKNAME: + default: + assert(false); + break; + } } uNodeDir = sleNode->getIFieldU64(sfIndexNext); diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index d2ce4c012..93d800c3f 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1151,22 +1151,12 @@ Json::Value RPCServer::doOwnerInfo(const Json::Value& params) uint256 uAccepted = mNetOps->getClosedLedger(); Json::Value jAccepted = accountFromString(uAccepted, naAccount, bIndex, strIdent, iIndex); - if (jAccepted.empty()) - { - jAccepted["offers"] = mNetOps->getOwnerInfo(uAccepted, naAccount); - } - - ret["accepted"] = jAccepted; + ret["accepted"] = jAccepted.empty() ? mNetOps->getOwnerInfo(uAccepted, naAccount) : jAccepted; uint256 uCurrent = mNetOps->getCurrentLedger(); Json::Value jCurrent = accountFromString(uCurrent, naAccount, bIndex, strIdent, iIndex); - if (jCurrent.empty()) - { - jCurrent["offers"] = mNetOps->getOwnerInfo(uCurrent, naAccount); - } - - ret["current"] = jCurrent; + ret["current"] = jCurrent.empty() ? mNetOps->getOwnerInfo(uCurrent, naAccount) : jCurrent; return ret; } @@ -1324,73 +1314,6 @@ Json::Value RPCServer::doPeers(const Json::Value& params) return obj; } -// ripple_line_set [] [] [] -Json::Value RPCServer::doRippleLineSet(const Json::Value& params) -{ - NewcoinAddress naSeed; - NewcoinAddress naSrcAccountID; - NewcoinAddress naDstAccountID; - STAmount saLimitAmount; - uint256 uLedger = mNetOps->getCurrentLedger(); - bool bLimitAmount = true; - bool bQualityIn = params.size() >= 6; - bool bQualityOut = params.size() >= 7; - uint32 uQualityIn = bQualityIn ? lexical_cast_s(params[5u].asString()) : 0; - uint32 uQualityOut = bQualityOut ? lexical_cast_s(params[6u].asString()) : 0; - - if (!naSeed.setSeedGeneric(params[0u].asString())) - { - return RPCError(rpcBAD_SEED); - } - else if (!naSrcAccountID.setAccountID(params[1u].asString())) - { - return RPCError(rpcSRC_ACT_MALFORMED); - } - else if (!naDstAccountID.setAccountID(params[2u].asString())) - { - return RPCError(rpcDST_ACT_MALFORMED); - } - else if (!saLimitAmount.setFullValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "")) - { - return RPCError(rpcSRC_AMT_MALFORMED); - } - else - { - NewcoinAddress naMasterGenerator; - NewcoinAddress naAccountPublic; - NewcoinAddress naAccountPrivate; - AccountState::pointer asSrc; - STAmount saSrcBalance; - Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, - saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); - - if (!obj.empty()) - return obj; - - Transaction::pointer trans = Transaction::sharedCreditSet( - naAccountPublic, naAccountPrivate, - naSrcAccountID, - asSrc->getSeq(), - theConfig.FEE_DEFAULT, - 0, // YYY No source tag - naDstAccountID, - bLimitAmount, saLimitAmount, - bQualityIn, uQualityIn, - bQualityOut, uQualityOut); - - trans = mNetOps->submitTransaction(trans); - - obj["transaction"] = trans->getSTransaction()->getJson(0); - obj["status"] = trans->getStatus(); - obj["seed"] = naSeed.humanSeed(); - obj["srcAccountID"] = naSrcAccountID.humanAccountID(); - obj["dstAccountID"] = naDstAccountID.humanAccountID(); - - return obj; - } -} - - // ripple // [noredeem] [noissue] // + @@ -1623,6 +1546,72 @@ Json::Value RPCServer::doRipple(const Json::Value ¶ms) return obj; } +// ripple_line_set [] [] [] +Json::Value RPCServer::doRippleLineSet(const Json::Value& params) +{ + NewcoinAddress naSeed; + NewcoinAddress naSrcAccountID; + NewcoinAddress naDstAccountID; + STAmount saLimitAmount; + uint256 uLedger = mNetOps->getCurrentLedger(); + bool bLimitAmount = true; + bool bQualityIn = params.size() >= 6; + bool bQualityOut = params.size() >= 7; + uint32 uQualityIn = bQualityIn ? lexical_cast_s(params[5u].asString()) : 0; + uint32 uQualityOut = bQualityOut ? lexical_cast_s(params[6u].asString()) : 0; + + if (!naSeed.setSeedGeneric(params[0u].asString())) + { + return RPCError(rpcBAD_SEED); + } + else if (!naSrcAccountID.setAccountID(params[1u].asString())) + { + return RPCError(rpcSRC_ACT_MALFORMED); + } + else if (!naDstAccountID.setAccountID(params[2u].asString())) + { + return RPCError(rpcDST_ACT_MALFORMED); + } + else if (!saLimitAmount.setFullValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "")) + { + return RPCError(rpcSRC_AMT_MALFORMED); + } + else + { + NewcoinAddress naMasterGenerator; + NewcoinAddress naAccountPublic; + NewcoinAddress naAccountPrivate; + AccountState::pointer asSrc; + STAmount saSrcBalance; + Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + saSrcBalance, theConfig.FEE_DEFAULT, asSrc, naMasterGenerator); + + if (!obj.empty()) + return obj; + + Transaction::pointer trans = Transaction::sharedCreditSet( + naAccountPublic, naAccountPrivate, + naSrcAccountID, + asSrc->getSeq(), + theConfig.FEE_DEFAULT, + 0, // YYY No source tag + naDstAccountID, + bLimitAmount, saLimitAmount, + bQualityIn, uQualityIn, + bQualityOut, uQualityOut); + + trans = mNetOps->submitTransaction(trans); + + obj["transaction"] = trans->getSTransaction()->getJson(0); + obj["status"] = trans->getStatus(); + obj["seed"] = naSeed.humanSeed(); + obj["srcAccountID"] = naSrcAccountID.humanAccountID(); + obj["dstAccountID"] = naDstAccountID.humanAccountID(); + + return obj; + } +} + // ripple_lines_get || [] Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) { @@ -1660,7 +1649,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) // We access a committed ledger and need not worry about changes. RippleLines rippleLines(naAccount.getAccountID()); - BOOST_FOREACH(RippleState::pointer line,rippleLines.getLines()) + BOOST_FOREACH(RippleState::pointer line, rippleLines.getLines()) { STAmount saBalance = line->getBalance(); STAmount saLimit = line->getLimit(); @@ -1668,15 +1657,17 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value ¶ms) Json::Value jPeer = Json::Value(Json::objectValue); - //jPeer["node"] = uNode.ToString(); + //jPeer["node"] = uNode.ToString(); - jPeer["account"] = line->getAccountIDPeer().humanAccountID(); + jPeer["account"] = line->getAccountIDPeer().humanAccountID(); // Amount reported is positive if current account holds other account's IOUs. // Amount reported is negative if other account holds current account's IOUs. - jPeer["balance"] = saBalance.getText(); - jPeer["currency"] = saBalance.getHumanCurrency(); - jPeer["limit"] = saLimit.getText(); - jPeer["limit_peer"] = saLimitPeer.getText(); + jPeer["balance"] = saBalance.getText(); + jPeer["currency"] = saBalance.getHumanCurrency(); + jPeer["limit"] = saLimit.getText(); + jPeer["limit_peer"] = saLimitPeer.getText(); + jPeer["quality_in"] = static_cast(line->getQualityIn()); + jPeer["quality_out"] = static_cast(line->getQualityOut()); jsonLines.append(jPeer); } diff --git a/src/RippleLines.cpp b/src/RippleLines.cpp index fce03685f..391d38c02 100644 --- a/src/RippleLines.cpp +++ b/src/RippleLines.cpp @@ -15,33 +15,40 @@ RippleLines::RippleLines(const uint160& accountID ) void RippleLines::fillLines(const uint160& accountID, Ledger::pointer ledger) { - uint256 rootIndex = Ledger::getRippleDirIndex(accountID); - uint256 currentIndex=rootIndex; + uint256 rootIndex = Ledger::getOwnerDirIndex(accountID); + uint256 currentIndex = rootIndex; - while(1) + LedgerStateParms lspNode = lepNONE; + + while (1) { - LedgerStateParms lspNode=lepNONE; - SerializedLedgerEntry::pointer rippleDir=ledger->getDirNode(lspNode,currentIndex); - if(!rippleDir) return; + SLE::pointer rippleDir=ledger->getDirNode(lspNode, currentIndex); + if (!rippleDir) return; - STVector256 svRippleNodes = rippleDir->getIFieldV256(sfIndexes); - BOOST_FOREACH(uint256& uNode, svRippleNodes.peekValue()) + STVector256 svOwnerNodes = rippleDir->getIFieldV256(sfIndexes); + BOOST_FOREACH(uint256& uNode, svOwnerNodes.peekValue()) { - RippleState::pointer rsLine = ledger->accessRippleState(uNode); - if (rsLine) + SLE::pointer sleCur = ledger->getSLE(uNode); + + if (ltRIPPLE_STATE == sleCur->getType()) { - rsLine->setViewAccount(accountID); - mLines.push_back(rsLine); - } - else - { - Log(lsWARNING) << "doRippleLinesGet: Bad index: " << uNode.ToString(); + RippleState::pointer rsLine = ledger->accessRippleState(uNode); + if (rsLine) + { + rsLine->setViewAccount(accountID); + mLines.push_back(rsLine); + } + else + { + Log(lsWARNING) << "doRippleLinesGet: Bad index: " << uNode.ToString(); + } } } - uint64 uNodeNext = rippleDir->getIFieldU64(sfIndexNext); - if(!uNodeNext) return; + uint64 uNodeNext = rippleDir->getIFieldU64(sfIndexNext); + if (!uNodeNext) return; currentIndex = Ledger::getDirNodeIndex(rootIndex, uNodeNext); } } +// vim:ts=4 diff --git a/src/RippleState.cpp b/src/RippleState.cpp index b4a4712d5..26a5bb707 100644 --- a/src/RippleState.cpp +++ b/src/RippleState.cpp @@ -7,11 +7,17 @@ RippleState::RippleState(SerializedLedgerEntry::pointer ledgerEntry) : { if (!mLedgerEntry || mLedgerEntry->getType() != ltRIPPLE_STATE) return; - mLowID = mLedgerEntry->getIValueFieldAccount(sfLowID); - mHighID = mLedgerEntry->getIValueFieldAccount(sfHighID); + mLowID = mLedgerEntry->getIValueFieldAccount(sfLowID); + mHighID = mLedgerEntry->getIValueFieldAccount(sfHighID); - mLowLimit = mLedgerEntry->getIValueFieldAmount(sfLowLimit); - mHighLimit = mLedgerEntry->getIValueFieldAmount(sfHighLimit); + mLowLimit = mLedgerEntry->getIValueFieldAmount(sfLowLimit); + mHighLimit = mLedgerEntry->getIValueFieldAmount(sfHighLimit); + + mLowQualityIn = mLedgerEntry->getIFieldU32(sfLowQualityIn); + mLowQualityOut = mLedgerEntry->getIFieldU32(sfLowQualityOut); + + mHighQualityIn = mLedgerEntry->getIFieldU32(sfHighQualityIn); + mHighQualityOut = mLedgerEntry->getIFieldU32(sfHighQualityOut); mBalance = mLedgerEntry->getIValueFieldAmount(sfBalance); diff --git a/src/RippleState.h b/src/RippleState.h index e4b34eab4..c83e6b364 100644 --- a/src/RippleState.h +++ b/src/RippleState.h @@ -24,6 +24,11 @@ private: STAmount mLowLimit; STAmount mHighLimit; + uint64 mLowQualityIn; + uint64 mLowQualityOut; + uint64 mHighQualityIn; + uint64 mHighQualityOut; + STAmount mBalance; bool mValid; @@ -42,6 +47,9 @@ public: STAmount getLimit() const { return mViewLowest ? mLowLimit : mHighLimit; } STAmount getLimitPeer() const { return mViewLowest ? mHighLimit : mLowLimit; } + uint32 getQualityIn() const { return mViewLowest ? mLowQualityIn : mHighQualityIn; } + uint32 getQualityOut() const { return mViewLowest ? mLowQualityOut : mHighQualityOut; } + SerializedLedgerEntry::pointer getSLE() { return mLedgerEntry; } const SerializedLedgerEntry& peekSLE() const { return *mLedgerEntry; } SerializedLedgerEntry& peekSLE() { return *mLedgerEntry; } diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index f6cc8edad..d957adf20 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -50,7 +50,7 @@ enum PathFlags PF_ISSUE = 0x80, }; -#define QUALITY_ONE 100000000 // 10e9 +#define QUALITY_ONE 1000000000 // 10e9 #define CURRENCY_XNS uint160(0) #define CURRENCY_ONE uint160(1) // Used as a place holder #define ACCOUNT_XNS uint160(0) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index da778890c..3f01d43f0 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -270,10 +270,10 @@ Transaction::pointer Transaction::setCreditSet( mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount); if (bQualityIn) - mTransaction->setITFieldU32(sfAcceptRate, uQualityIn); + mTransaction->setITFieldU32(sfQualityIn, uQualityIn); if (bQualityOut) - mTransaction->setITFieldU32(sfAcceptRate, uQualityOut); + mTransaction->setITFieldU32(sfQualityOut, uQualityOut); sign(naPrivateKey); diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 17299b346..c7df73f46 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -145,7 +145,7 @@ STAmount TransactionEngine::rippleLimit(const uint160& uToAccountID, const uint1 } -uint32 TransactionEngine::rippleTransfer(const uint160& uIssuerID) +uint32 TransactionEngine::rippleTransferRate(const uint160& uIssuerID) { SLE::pointer sleAccount = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uIssuerID)); @@ -298,13 +298,13 @@ STAmount TransactionEngine::accountFunds(const uint160& uAccountID, const STAmou } // Calculate transit fee. -STAmount TransactionEngine::rippleTransfer(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount) +STAmount TransactionEngine::rippleTransferFee(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount) { STAmount saTransitFee; if (uSenderID != uIssuerID && uReceiverID != uIssuerID) { - uint32 uTransitRate = rippleTransfer(uIssuerID); + uint32 uTransitRate = rippleTransferRate(uIssuerID); if (QUALITY_ONE != uTransitRate) { @@ -380,7 +380,7 @@ STAmount TransactionEngine::rippleSend(const uint160& uSenderID, const uint160& { // Sending 3rd party IOUs: transit. - STAmount saTransitFee = rippleTransfer(uSenderID, uReceiverID, uIssuerID, saAmount); + STAmount saTransitFee = rippleTransferFee(uSenderID, uReceiverID, uIssuerID, saAmount); saActual = saTransitFee.isZero() ? saAmount : saAmount+saTransitFee; @@ -1504,8 +1504,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti return terNO_DST; } - bool bFlipped = mTxnAccountID > uDstAccountID; - uint32 uFlags = bFlipped ? lsfLowIndexed : lsfHighIndexed; + bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest. bool bLimitAmount = txn.getITFieldPresent(sfLimitAmount); STAmount saLimitAmount = bLimitAmount ? txn.getITFieldAmount(sfLimitAmount) : STAmount(); bool bQualityIn = txn.getITFieldPresent(sfQualityIn); @@ -1514,7 +1513,6 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti uint32 uQualityOut = bQualityIn ? txn.getITFieldU32(sfQualityOut) : 0; uint160 uCurrencyID = saLimitAmount.getCurrency(); STAmount saBalance(uCurrencyID); - bool bAddIndex = false; bool bDelIndex = false; SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID)); @@ -1540,7 +1538,7 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti // Zero balance and eliminating last limit. bDelIndex = true; - terResult = dirDelete(false, uSrcRef, Ledger::getRippleDirIndex(mTxnAccountID), sleRippleState->getIndex()); + terResult = dirDelete(false, uSrcRef, Ledger::getOwnerDirIndex(mTxnAccountID), sleRippleState->getIndex()); } } #endif @@ -1576,15 +1574,10 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti sleRippleState->makeIFieldAbsent(bFlipped ? sfLowQualityOut : sfHighQualityOut); } - bAddIndex = !(sleRippleState->getFlags() & uFlags); - - if (bAddIndex) - sleRippleState->setFlag(uFlags); - entryModify(sleRippleState); } - Log(lsINFO) << "doCreditSet: Modifying ripple line: bAddIndex=" << bAddIndex << " bDelIndex=" << bDelIndex; + Log(lsINFO) << "doCreditSet: Modifying ripple line: bDelIndex=" << bDelIndex; } // Line does not exist. else if (saLimitAmount.isZero()) @@ -1596,31 +1589,26 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti else { // Create a new ripple line. - STAmount saZero(uCurrencyID); - - bAddIndex = true; sleRippleState = entryCreate(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID)); Log(lsINFO) << "doCreditSet: Creating ripple line: " << sleRippleState->getIndex().ToString(); - sleRippleState->setFlag(uFlags); - sleRippleState->setIFieldAmount(sfBalance, saZero); // Zero balance in currency. + sleRippleState->setIFieldAmount(sfBalance, STAmount(uCurrencyID)); // Zero balance in currency. sleRippleState->setIFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, saLimitAmount); - sleRippleState->setIFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, saZero); + sleRippleState->setIFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, STAmount(uCurrencyID)); sleRippleState->setIFieldAccount(bFlipped ? sfHighID : sfLowID, mTxnAccountID); sleRippleState->setIFieldAccount(bFlipped ? sfLowID : sfHighID, uDstAccountID); if (uQualityIn) - sleRippleState->setIFieldU32(bFlipped ? sfLowQualityIn : sfHighQualityIn, uQualityIn); + sleRippleState->setIFieldU32(bFlipped ? sfHighQualityIn : sfLowQualityIn, uQualityIn); if (uQualityOut) - sleRippleState->setIFieldU32(bFlipped ? sfLowQualityOut : sfHighQualityOut, uQualityOut); - } + sleRippleState->setIFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut); - if (bAddIndex) - { - uint64 uSrcRef; // Ignored, ripple_state dirs never delete. + uint64 uSrcRef; // Ignored, dirs never delete. - // XXX Make dirAdd more flexiable to take vector. - terResult = dirAdd(uSrcRef, Ledger::getRippleDirIndex(mTxnAccountID), sleRippleState->getIndex()); + terResult = dirAdd(uSrcRef, Ledger::getOwnerDirIndex(mTxnAccountID), sleRippleState->getIndex()); + + if (terSUCCESS == terResult) + terResult = dirAdd(uSrcRef, Ledger::getOwnerDirIndex(uDstAccountID), sleRippleState->getIndex()); } Log(lsINFO) << "doCreditSet<"; @@ -1927,16 +1915,16 @@ bool TransactionEngine::calcNodeOfferRev( uint160& uNxtIssuerID = nxtPN.uIssuerID; uint160& uNxtAccountID = nxtPN.uAccountID; - STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransfer(uCurIssuerID), -9); + STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9); uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID); uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip); bool bAdvance = !entryCache(ltDIR_NODE, uDirectTip); - STAmount& saPrvDlvReq = prvPN.saRevDeliver; + STAmount& saPrvDlvReq = prvPN.saRevDeliver; // To be adjusted. STAmount saPrvDlvAct; - STAmount& saCurDlvReq = curPN.saRevDeliver; // Reverse driver. + const STAmount& saCurDlvReq = curPN.saRevDeliver; // Reverse driver. STAmount saCurDlvAct; while (!!uDirectTip // Have a quality. @@ -2119,7 +2107,7 @@ bool TransactionEngine::calcNodeOfferFwd( uint160& uNxtIssuerID = nxtPN.uIssuerID; uint160& uNxtAccountID = nxtPN.uAccountID; - STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransfer(uCurIssuerID), -9); + STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9); uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID); uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip); @@ -2515,7 +2503,7 @@ void TransactionEngine::calcNodeOffer( // saPrvReq -> saCurReq // sqPrvAct -> saCurAct // This is a minimizing routine: moving in reverse it propagates the send limit to the sender, moving forward it propagates the -// actual send toward the reciver. +// actual send toward the receiver. // This routine works backwards as it calculates previous wants based on previous credit limits and current wants. // This routine works forwards as it calculates current deliver based on previous delivery limits and current wants. // XXX Deal with uQualityIn or uQualityOut = 0 @@ -2541,8 +2529,6 @@ void TransactionEngine::calcNodeRipple( STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct; STAmount saCur = saCurReq-saCurAct; - Log(lsINFO) << str(boost::format("calcNodeRipple:1: saCurReq=%s") % saCurReq.getFullText()); - #if 0 Log(lsINFO) << str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s") % bPrvUnlimited @@ -2553,6 +2539,8 @@ void TransactionEngine::calcNodeRipple( if (uQualityIn >= uQualityOut) { // No fee. + Log(lsINFO) << str(boost::format("calcNodeRipple: No fees")); + STAmount saTransfer = bPrvUnlimited ? saCur : MIN(saPrv, saCur); saPrvAct += saTransfer; @@ -2561,15 +2549,16 @@ void TransactionEngine::calcNodeRipple( else { // Fee. + Log(lsINFO) << str(boost::format("calcNodeRipple: Fee")); + uint160 uCurrencyID = saCur.getCurrency(); STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, uCurrencyID), uQualityIn, uCurrencyID); -Log(lsINFO) << str(boost::format("calcNodeRipple:2: saCurReq=%s") % saCurReq.getFullText()); - if (bPrvUnlimited || saCurIn >= saPrv) +Log(lsINFO) << str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCurIn=%s") % bPrvUnlimited % saPrv.getFullText() % saCurIn.getFullText()); + if (bPrvUnlimited || saCurIn <= saPrv) { // All of cur. Some amount of prv. -Log(lsINFO) << str(boost::format("calcNodeRipple:3a: saCurReq=%s") % saCurReq.getFullText()); - saCurAct = saCurReq; + saCurAct += saCur; saPrvAct += saCurIn; Log(lsINFO) << str(boost::format("calcNodeRipple:3c: saCurReq=%s saPrvAct=%s") % saCurReq.getFullText() % saPrvAct.getFullText()); } @@ -2730,7 +2719,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point // Rate : 1.0 : transfer_rate Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate : 1.0 : transfer_rate")); - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); } // issue (part 1)-> redeem @@ -2789,7 +2778,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saCurDeliverReq) // Need some issued. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct); } // issue -> deliver/issue @@ -2848,7 +2837,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saCurIssueReq) // Need some issued. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvDeliverReq, saCurIssueReq, saPrvDeliverAct, saCurIssueAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurIssueReq, saPrvDeliverAct, saCurIssueAct); } if (!saCurDeliverAct && !saCurIssueAct) @@ -2869,7 +2858,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point && saCurDeliverReq != saCurDeliverAct) // Can only if issue if more can not be redeemed. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvDeliverReq, saCurDeliverReq, saPrvDeliverAct, saCurDeliverAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurDeliverReq, saPrvDeliverAct, saCurDeliverAct); } if (!saCurDeliverAct) @@ -3041,7 +3030,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point && saCurIssueReq) { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); } // Previous issue part 1: issue -> redeem @@ -3077,7 +3066,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point if (saPrvRedeemReq) // Previous wants to redeem. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurDeliverReq, saPrvRedeemAct, saCurDeliverAct); } // issue -> issue @@ -3125,7 +3114,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point && saCurIssueReq) // Current wants issue. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct); } // No income balance adjustments necessary. The paying side inside the offer paid and the next link will receive. @@ -3142,7 +3131,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point && saCurIssueReq) // Current wants issue. { // Rate : 1.0 : transfer_rate - calcNodeRipple(QUALITY_ONE, rippleTransfer(uCurAccountID), saPrvDeliverReq, saCurDeliverReq, saPrvDeliverAct, saCurDeliverAct); + calcNodeRipple(QUALITY_ONE, rippleTransferRate(uCurAccountID), saPrvDeliverReq, saCurDeliverReq, saPrvDeliverAct, saCurDeliverAct); } // No income balance adjustments necessary. The paying side inside the offer paid and the next link will receive. @@ -3742,7 +3731,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction terResult = dirAdd( uSrcRef, - Ledger::getRippleDirIndex(mTxnAccountID), // The source ended up owing. + Ledger::getOwnerDirIndex(mTxnAccountID), // The source ended up owing. sleRippleState->getIndex()); // Adding current entry. if (terSUCCESS != terResult) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 717074194..5df286d74 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -221,14 +221,14 @@ protected: void entryDelete(SLE::pointer sleEntry, bool unfunded = false); void entryModify(SLE::pointer sleEntry); - uint32 rippleTransfer(const uint160& uIssuerID); + uint32 rippleTransferRate(const uint160& uIssuerID); STAmount rippleBalance(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); STAmount rippleLimit(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); uint32 rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); uint32 rippleQualityOut(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID); - STAmount rippleTransfer(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount); + STAmount rippleTransferFee(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount); void rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount, bool bCheckIssuer=true); STAmount rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);