Merge branch 'master' of github.com:jedmccaleb/NewCoin

Conflicts:
	src/RippleLines.cpp
This commit is contained in:
jed
2012-08-20 09:40:40 -07:00
14 changed files with 382 additions and 379 deletions

View File

@@ -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<SHAMapItem>(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<SLE>(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<SLE>(let);
sle->setIndex(nodeID);
return sle;
}
SLE::pointer sle =
boost::make_shared<SLE>(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

View File

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

View File

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

View File

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

View File

@@ -1,200 +1,5 @@
#include "Ledger.h"
#include <boost/make_shared.hpp>
#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<SHAMapItem>(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<SLE>(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<SLE>(let);
sle->setIndex(nodeID);
return sle;
}
SLE::pointer sle =
boost::make_shared<SLE>(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

View File

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

View File

@@ -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 <seed> <paying_account> <destination_account> <limit_amount> [<currency>] [<quality_in>] [<quality_out>]
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<uint32>(params[5u].asString()) : 0;
uint32 uQualityOut = bQualityOut ? lexical_cast_s<uint32>(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 <regular_seed> <paying_account>
// <source_max> <source_currency> <source_issuerID> [noredeem] [noissue]
// <path>+
@@ -1623,6 +1546,72 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
return obj;
}
// ripple_line_set <seed> <paying_account> <destination_account> <limit_amount> [<currency>] [<quality_in>] [<quality_out>]
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<uint32>(params[5u].asString()) : 0;
uint32 uQualityOut = bQualityOut ? lexical_cast_s<uint32>(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 <account>|<nickname>|<account_public_key> [<index>]
Json::Value RPCServer::doRippleLinesGet(const Json::Value &params)
{
@@ -1660,7 +1649,7 @@ Json::Value RPCServer::doRippleLinesGet(const Json::Value &params)
// 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 &params)
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<Json::UInt>(line->getQualityIn());
jPeer["quality_out"] = static_cast<Json::UInt>(line->getQualityOut());
jsonLines.append(jPeer);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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