Merge branch 'ripple'

This commit is contained in:
Arthur Britto
2012-08-17 17:12:47 -07:00
6 changed files with 330 additions and 81 deletions

View File

@@ -880,6 +880,30 @@ STAmount STAmount::deserialize(SerializerIterator& it)
} }
std::string STAmount::getFullText() const std::string STAmount::getFullText() const
{
if (mIsNative)
{
return str(boost::format("%s/" SYSTEM_CURRENCY_CODE) % getText());
}
else if (!mIssuer)
{
return str(boost::format("%s/%s/0") % getText() % getHumanCurrency());
}
else if (mIssuer == ACCOUNT_ONE)
{
return str(boost::format("%s/%s/1") % getText() % getHumanCurrency());
}
else
{
return str(boost::format("%s/%s/%s")
% getText()
% getHumanCurrency()
% NewcoinAddress::createHumanAccountID(mIssuer));
}
}
#if 0
std::string STAmount::getExtendedText() const
{ {
if (mIsNative) if (mIsNative)
{ {
@@ -887,7 +911,7 @@ std::string STAmount::getFullText() const
} }
else else
{ {
return str(boost::format("%s %s/%s %dE%d" ) return str(boost::format("%s/%s/%s %dE%d" )
% getText() % getText()
% getHumanCurrency() % getHumanCurrency()
% NewcoinAddress::createHumanAccountID(mIssuer) % NewcoinAddress::createHumanAccountID(mIssuer)
@@ -895,6 +919,7 @@ std::string STAmount::getFullText() const
% getExponent()); % getExponent());
} }
} }
#endif
Json::Value STAmount::getJson(int) const Json::Value STAmount::getJson(int) const
{ {

View File

@@ -6,6 +6,7 @@
#include <openssl/rand.h> #include <openssl/rand.h>
#include "utils.h" #include "utils.h"
#include "Config.h"
#include "Log.h" #include "Log.h"
// #define SNTP_DEBUG // #define SNTP_DEBUG
@@ -43,6 +44,8 @@ static uint8_t SNTPQueryData[48] =
SNTPClient::SNTPClient(boost::asio::io_service& service) : mSocket(service), mTimer(service), mResolver(service), SNTPClient::SNTPClient(boost::asio::io_service& service) : mSocket(service), mTimer(service), mResolver(service),
mOffset(0), mLastOffsetUpdate((time_t) -1), mReceiveBuffer(256) mOffset(0), mLastOffsetUpdate((time_t) -1), mReceiveBuffer(256)
{ {
if (!theConfig.RUN_STANDALONE)
{
mSocket.open(boost::asio::ip::udp::v4()); mSocket.open(boost::asio::ip::udp::v4());
mSocket.async_receive_from(boost::asio::buffer(mReceiveBuffer, 256), mReceiveEndpoint, mSocket.async_receive_from(boost::asio::buffer(mReceiveBuffer, 256), mReceiveEndpoint,
boost::bind(&SNTPClient::receivePacket, this, boost::asio::placeholders::error, boost::bind(&SNTPClient::receivePacket, this, boost::asio::placeholders::error,
@@ -50,6 +53,7 @@ SNTPClient::SNTPClient(boost::asio::io_service& service) : mSocket(service), mTi
mTimer.expires_from_now(boost::posix_time::seconds(NTP_QUERY_FREQUENCY)); mTimer.expires_from_now(boost::posix_time::seconds(NTP_QUERY_FREQUENCY));
mTimer.async_wait(boost::bind(&SNTPClient::timerEntry, this, boost::asio::placeholders::error)); mTimer.async_wait(boost::bind(&SNTPClient::timerEntry, this, boost::asio::placeholders::error));
}
} }
void SNTPClient::resolveComplete(const boost::system::error_code& error, boost::asio::ip::udp::resolver::iterator it) void SNTPClient::resolveComplete(const boost::system::error_code& error, boost::asio::ip::udp::resolver::iterator it)
@@ -247,3 +251,4 @@ bool SNTPClient::doQuery()
#endif #endif
return true; return true;
} }
// vim:ts=4

View File

@@ -56,3 +56,4 @@ public:
}; };
#endif #endif
// vim:ts=4

View File

@@ -50,6 +50,12 @@ enum PathFlags
PF_ISSUE = 0x80, PF_ISSUE = 0x80,
}; };
#define QUALITY_ONE 100000000 // 10e9
#define CURRENCY_XNS uint160(0)
#define CURRENCY_ONE uint160(1) // Used as a place holder
#define ACCOUNT_XNS uint160(0)
#define ACCOUNT_ONE uint160(1) // Used as a place holder
class SerializedType class SerializedType
{ {
protected: protected:

View File

@@ -21,12 +21,6 @@
#define DIR_NODE_MAX 2 #define DIR_NODE_MAX 2
#define RIPPLE_PATHS_MAX 3 #define RIPPLE_PATHS_MAX 3
#define QUALITY_ONE 100000000 // 10e9
#define CURRENCY_XNS uint160(0)
#define CURRENCY_ONE uint160(1) // Used as a place holder
#define ACCOUNT_XNS uint160(0)
#define ACCOUNT_ONE uint160(1) // Used as a place holder
static STAmount saZero(CURRENCY_ONE, 0, 0); static STAmount saZero(CURRENCY_ONE, 0, 0);
static STAmount saOne(CURRENCY_ONE, 1, 0); static STAmount saOne(CURRENCY_ONE, 1, 0);
@@ -113,13 +107,24 @@ STAmount TransactionEngine::rippleBalance(const uint160& uToAccountID, const uin
STAmount saBalance; STAmount saBalance;
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(uToAccountID, uFromAccountID, uCurrencyID)); SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(uToAccountID, uFromAccountID, uCurrencyID));
assert(sleRippleState);
if (sleRippleState) if (sleRippleState)
{ {
saBalance = sleRippleState->getIValueFieldAmount(sfBalance); saBalance = sleRippleState->getIValueFieldAmount(sfBalance);
if (uToAccountID < uFromAccountID) if (uToAccountID < uFromAccountID)
saBalance.negate(); saBalance.negate();
} }
else
{
Log(lsINFO) << "rippleBalance: No credit line between "
<< NewcoinAddress::createHumanAccountID(uFromAccountID)
<< " and "
<< NewcoinAddress::createHumanAccountID(uToAccountID)
<< " for "
<< STAmount::createHumanCurrency(uCurrencyID)
<< "." ;
assert(false);
}
return saBalance; return saBalance;
@@ -164,7 +169,13 @@ uint32 TransactionEngine::rippleQualityIn(const uint160& uToAccountID, const uin
if (sleRippleState) if (sleRippleState)
{ {
uQualityIn = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityIn : sfHighQualityIn); SOE_Field sfField = uToAccountID < uFromAccountID ? sfLowQualityIn : sfHighQualityIn;
uQualityIn = sleRippleState->getIFieldPresent(sfField)
? sleRippleState->getIFieldU32(sfField)
: QUALITY_ONE;
if (!uQualityIn)
uQualityIn = 1;
} }
else else
{ {
@@ -190,6 +201,8 @@ uint32 TransactionEngine::rippleQualityOut(const uint160& uToAccountID, const ui
if (sleRippleState) if (sleRippleState)
{ {
uQualityOut = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityOut : sfHighQualityOut); uQualityOut = sleRippleState->getIFieldU32(uToAccountID < uFromAccountID ? sfLowQualityOut : sfHighQualityOut);
if (!uQualityOut)
uQualityOut = 1;
} }
else else
{ {
@@ -305,11 +318,11 @@ STAmount TransactionEngine::rippleTransfer(const uint160& uSenderID, const uint1
} }
// Direct send w/o fees: redeeming IOUs and/or sending own IOUs. // Direct send w/o fees: redeeming IOUs and/or sending own IOUs.
void TransactionEngine::rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount) void TransactionEngine::rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount, bool bCheckIssuer)
{ {
uint160 uIssuerID = saAmount.getIssuer(); uint160 uIssuerID = saAmount.getIssuer();
assert(uSenderID == uIssuerID || uReceiverID == uIssuerID); assert(!bCheckIssuer || uSenderID == uIssuerID || uReceiverID == uIssuerID);
bool bFlipped = uSenderID > uReceiverID; bool bFlipped = uSenderID > uReceiverID;
uint256 uIndex = Ledger::getRippleStateIndex(uSenderID, uReceiverID, saAmount.getCurrency()); uint256 uIndex = Ledger::getRippleStateIndex(uSenderID, uReceiverID, saAmount.getCurrency());
@@ -2505,6 +2518,7 @@ void TransactionEngine::calcNodeOffer(
// actual send toward the reciver. // actual send toward the reciver.
// This routine works backwards as it calculates previous wants based on previous credit limits and current wants. // 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. // This routine works forwards as it calculates current deliver based on previous delivery limits and current wants.
// XXX Deal with uQualityIn or uQualityOut = 0
void TransactionEngine::calcNodeRipple( void TransactionEngine::calcNodeRipple(
const uint32 uQualityIn, const uint32 uQualityIn,
const uint32 uQualityOut, const uint32 uQualityOut,
@@ -2513,10 +2527,29 @@ void TransactionEngine::calcNodeRipple(
STAmount& saPrvAct, // <-> in limit including achieved STAmount& saPrvAct, // <-> in limit including achieved
STAmount& saCurAct) // <-> out limit achieved. STAmount& saCurAct) // <-> out limit achieved.
{ {
Log(lsINFO) << str(boost::format("calcNodeRipple> uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
% uQualityIn
% uQualityOut
% saPrvReq.getFullText()
% saCurReq.getFullText()
% saPrvAct.getFullText()
% saCurAct.getFullText());
assert(saPrvReq.getCurrency() == saCurReq.getCurrency());
bool bPrvUnlimited = saPrvReq.isNegative(); bool bPrvUnlimited = saPrvReq.isNegative();
STAmount saPrv = bPrvUnlimited ? saZero : saPrvReq-saPrvAct; STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct;
STAmount saCur = saCurReq-saCurAct; 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
% saPrv.getFullText()
% saCur.getFullText());
#endif
if (uQualityIn >= uQualityOut) if (uQualityIn >= uQualityOut)
{ {
// No fee. // No fee.
@@ -2528,23 +2561,37 @@ void TransactionEngine::calcNodeRipple(
else else
{ {
// Fee. // Fee.
STAmount saCurIn = STAmount::divide(STAmount::multiply(saCur, uQualityOut, CURRENCY_ONE), uQualityIn, CURRENCY_ONE); 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) if (bPrvUnlimited || saCurIn >= saPrv)
{ {
// All of cur. Some amount of prv. // All of cur. Some amount of prv.
Log(lsINFO) << str(boost::format("calcNodeRipple:3a: saCurReq=%s") % saCurReq.getFullText());
saCurAct = saCurReq; saCurAct = saCurReq;
saPrvAct += saCurIn; saPrvAct += saCurIn;
Log(lsINFO) << str(boost::format("calcNodeRipple:3c: saCurReq=%s saPrvAct=%s") % saCurReq.getFullText() % saPrvAct.getFullText());
} }
else else
{ {
// A part of cur. All of prv. (cur as driver) // A part of cur. All of prv. (cur as driver)
STAmount saCurOut = STAmount::divide(STAmount::multiply(saPrv, uQualityIn, CURRENCY_ONE), uQualityOut, CURRENCY_ONE); uint160 uCurrencyID = saPrv.getCurrency();
STAmount saCurOut = STAmount::divide(STAmount::multiply(saPrv, uQualityIn, uCurrencyID), uQualityOut, uCurrencyID);
Log(lsINFO) << str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCurReq.getFullText());
saCurAct += saCurOut; saCurAct += saCurOut;
saPrvAct = saPrvReq; saPrvAct = saPrvReq;
} }
} }
Log(lsINFO) << str(boost::format("calcNodeRipple< uQualityIn=%d uQualityOut=%d saPrvReq=%s saCurReq=%s saPrvAct=%s saCurAct=%s")
% uQualityIn
% uQualityOut
% saPrvReq.getFullText()
% saCurReq.getFullText()
% saPrvAct.getFullText()
% saCurAct.getFullText());
} }
// Calculate saPrvRedeemReq, saPrvIssueReq, saPrvDeliver; // Calculate saPrvRedeemReq, saPrvIssueReq, saPrvDeliver;
@@ -2561,59 +2608,80 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
bool bPrvRedeem = !!(prvPN.uFlags & STPathElement::typeRedeem); bool bPrvRedeem = !!(prvPN.uFlags & STPathElement::typeRedeem);
bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue); bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue);
bool bPrvIssue = !!(prvPN.uFlags & STPathElement::typeIssue); bool bPrvIssue = !!(prvPN.uFlags & STPathElement::typeIssue);
bool bPrvAccount = !!(prvPN.uFlags & STPathElement::typeAccount); bool bPrvAccount = !uIndex || !!(prvPN.uFlags & STPathElement::typeAccount);
bool bNxtAccount = !!(nxtPN.uFlags & STPathElement::typeAccount); bool bNxtAccount = uIndex == uLast || !!(nxtPN.uFlags & STPathElement::typeAccount);
uint160& uPrvAccountID = prvPN.uAccountID; const uint160& uPrvAccountID = prvPN.uAccountID;
uint160& uCurAccountID = curPN.uAccountID; const uint160& uCurAccountID = curPN.uAccountID;
uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue. const uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue.
uint160& uCurrencyID = curPN.uCurrencyID; const uint160& uCurrencyID = curPN.uCurrencyID;
uint32 uQualityIn = rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID); const uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 1;
uint32 uQualityOut = rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID); const uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 1;
// For bPrvAccount // For bPrvAccount
STAmount saPrvBalance = bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : saZero; const STAmount saPrvBalance = uIndex && bPrvAccount ? rippleBalance(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID);
STAmount saPrvLimit = bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : saZero; const STAmount saPrvLimit = uIndex && bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID);
STAmount saPrvRedeemReq = bPrvRedeem && saPrvBalance.isNegative() ? -saPrvBalance : STAmount(uCurrencyID, 0); const STAmount saPrvRedeemReq = bPrvRedeem && saPrvBalance.isNegative() ? -saPrvBalance : STAmount(uCurrencyID, 0);
STAmount& saPrvRedeemAct = prvPN.saRevRedeem; STAmount& saPrvRedeemAct = prvPN.saRevRedeem;
STAmount saPrvIssueReq = bPrvIssue && saPrvLimit - saPrvBalance; const STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID);
STAmount& saPrvIssueAct = prvPN.saRevIssue; STAmount& saPrvIssueAct = prvPN.saRevIssue;
// For !bPrvAccount // For !bPrvAccount
STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited. const STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited.
STAmount& saPrvDeliverAct = prvPN.saRevDeliver; STAmount& saPrvDeliverAct = prvPN.saRevDeliver;
// For bNxtAccount // For bNxtAccount
const STAmount& saCurRedeemReq = curPN.saRevRedeem; const STAmount& saCurRedeemReq = curPN.saRevRedeem;
STAmount saCurRedeemAct; STAmount saCurRedeemAct(saCurRedeemReq.getCurrency());
const STAmount& saCurIssueReq = curPN.saRevIssue; const STAmount& saCurIssueReq = curPN.saRevIssue;
STAmount saCurIssueAct; // Track progress. STAmount saCurIssueAct(saCurIssueReq.getCurrency()); // Track progress.
// For !bNxtAccount // For !bNxtAccount
const STAmount& saCurDeliverReq = curPN.saRevDeliver; const STAmount& saCurDeliverReq = curPN.saRevDeliver;
STAmount saCurDeliverAct; STAmount saCurDeliverAct(saCurDeliverReq.getCurrency());
// For uIndex == uLast // For uIndex == uLast
const STAmount& saCurWantedReq = pspCur->saOutReq; // XXX Credit limits? const STAmount& saCurWantedReq = pspCur->saOutReq; // XXX Credit limits?
// STAmount saPrvDeliverReq = saPrvBalance.isPositive() ? saPrvLimit - saPrvBalance : saPrvLimit; // STAmount saPrvDeliverReq = saPrvBalance.isPositive() ? saPrvLimit - saPrvBalance : saPrvLimit;
STAmount saCurWantedAct; STAmount saCurWantedAct(saCurWantedReq.getCurrency());
Log(lsINFO) << str(boost::format("calcNodeAccountRev> uIndex=%d/%d saPrvRedeemReq=%s/%s saPrvIssueReq=%s/%s saCurWantedReq=%s/%s")
% uIndex
% uLast
% saPrvRedeemReq.getText()
% saPrvRedeemReq.getHumanCurrency()
% saPrvIssueReq.getText()
% saPrvIssueReq.getHumanCurrency()
% saCurWantedReq.getText()
% saCurWantedReq.getHumanCurrency());
Log(lsINFO) << pspCur->getJson();
if (bPrvAccount && bNxtAccount) if (bPrvAccount && bNxtAccount)
{ {
if (uIndex == uLast) if (!uIndex)
{
// ^ --> ACCOUNT --> account|offer
// Nothing to do, there is no previous to adjust.
nothing();
}
else if (uIndex == uLast)
{ {
// account --> ACCOUNT --> $ // account --> ACCOUNT --> $
Log(lsINFO) << str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> $"));
// Calculate redeem // Calculate redeem
if (bRedeem if (bRedeem
&& saPrvRedeemReq) // Previous has IOUs to redeem. && saPrvRedeemReq) // Previous has IOUs to redeem.
{ {
// Redeem at 1:1 // Redeem at 1:1
Log(lsINFO) << str(boost::format("calcNodeAccountRev: Redeem at 1:1"));
saCurWantedAct = MIN(saPrvRedeemReq, saCurWantedReq); saCurWantedAct = MIN(saPrvRedeemReq, saCurWantedReq);
saPrvRedeemAct = saCurWantedAct; saPrvRedeemAct = saCurWantedAct;
} }
@@ -2624,6 +2692,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
&& saPrvIssueReq) // Will accept IOUs. && saPrvIssueReq) // Will accept IOUs.
{ {
// Rate: quality in : 1.0 // Rate: quality in : 1.0
Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurWantedReq, saPrvIssueAct, saCurWantedAct); calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurWantedReq, saPrvIssueAct, saCurWantedAct);
} }
@@ -2636,7 +2706,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
} }
else else
{ {
// account --> ACCOUNT --> account // ^|account --> ACCOUNT --> account
// redeem (part 1) -> redeem // redeem (part 1) -> redeem
if (bPrvRedeem if (bPrvRedeem
@@ -2645,6 +2715,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
&& saPrvBalance.isNegative()) // Previous has IOUs to redeem. && saPrvBalance.isNegative()) // Previous has IOUs to redeem.
{ {
// Rate : 1.0 : quality out // Rate : 1.0 : quality out
Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate : 1.0 : quality out"));
calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvRedeemReq, saCurRedeemReq, saPrvRedeemAct, saCurRedeemAct); calcNodeRipple(QUALITY_ONE, uQualityOut, saPrvRedeemReq, saCurRedeemReq, saPrvRedeemAct, saCurRedeemAct);
} }
@@ -2656,6 +2728,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
&& saCurIssueReq) // Need some issued. && saCurIssueReq) // Need some issued.
{ {
// Rate : 1.0 : transfer_rate // 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, rippleTransfer(uCurAccountID), saPrvRedeemReq, saCurIssueReq, saPrvRedeemAct, saCurIssueAct);
} }
@@ -2666,17 +2740,21 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
&& !saPrvBalance.isNegative()) // Previous has no IOUs. && !saPrvBalance.isNegative()) // Previous has no IOUs.
{ {
// Rate: quality in : quality out // Rate: quality in : quality out
Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : quality out"));
calcNodeRipple(uQualityIn, uQualityOut, saPrvIssueReq, saCurRedeemReq, saPrvIssueAct, saCurRedeemAct); calcNodeRipple(uQualityIn, uQualityOut, saPrvIssueReq, saCurRedeemReq, saPrvIssueAct, saCurRedeemAct);
} }
// issue (part 2) -> issue // issue (part 2) -> issue
if (bPrvIssue if (bPrvIssue
&& bIssue // Allowed to issue. && bIssue // Allowed to issue.
&& saCurRedeemReq != saCurRedeemAct // Can only if issue if more can not be redeemed. && saCurRedeemReq == saCurRedeemAct // Can only if issue if more can not be redeemed.
&& !saPrvBalance.isNegative() // Previous has no IOUs. && !saPrvBalance.isNegative() // Previous has no IOUs.
&& saCurIssueReq != saCurIssueAct) // Need some issued. && saCurIssueReq != saCurIssueAct) // Need some issued.
{ {
// Rate: quality in : 1.0 // Rate: quality in : 1.0
Log(lsINFO) << str(boost::format("calcNodeAccountRev: Rate: quality in : 1.0"));
calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurIssueReq, saPrvIssueAct, saCurIssueAct); calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvIssueReq, saCurIssueReq, saPrvIssueAct, saCurIssueAct);
} }
@@ -2686,12 +2764,23 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
// terResult = tenBAD_AMOUNT; // terResult = tenBAD_AMOUNT;
bSuccess = false; bSuccess = false;
} }
Log(lsINFO) << str(boost::format("calcNodeAccountRev: ^|account --> ACCOUNT --> account : bPrvRedeem=%d bPrvIssue=%d bRedeem=%d bIssue=%d saCurRedeemReq=%s saCurIssueReq=%s saPrvBalance=%s saCurRedeemAct=%s saCurIssueAct=%s")
% bPrvRedeem
% bPrvIssue
% bRedeem
% bIssue
% saCurRedeemReq.getFullText()
% saCurIssueReq.getFullText()
% saPrvBalance.getFullText()
% saCurRedeemAct.getFullText()
% saCurIssueAct.getFullText());
} }
} }
else if (bPrvAccount && !bNxtAccount) else if (bPrvAccount && !bNxtAccount)
{ {
// account --> ACCOUNT --> offer // account --> ACCOUNT --> offer
// Note: deliver is always issue as ACCOUNT is the issuer for the offer input. // Note: deliver is always issue as ACCOUNT is the issuer for the offer input.
Log(lsINFO) << str(boost::format("calcNodeAccountRev: account --> ACCOUNT --> offer"));
// redeem -> deliver/issue. // redeem -> deliver/issue.
if (bPrvRedeem if (bPrvRedeem
@@ -2725,6 +2814,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
if (uIndex == uLast) if (uIndex == uLast)
{ {
// offer --> ACCOUNT --> $ // offer --> ACCOUNT --> $
Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> $"));
// Rate: quality in : 1.0 // Rate: quality in : 1.0
calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvDeliverReq, saCurWantedReq, saPrvDeliverAct, saCurWantedAct); calcNodeRipple(uQualityIn, QUALITY_ONE, saPrvDeliverReq, saCurWantedReq, saPrvDeliverAct, saCurWantedAct);
@@ -2740,6 +2830,7 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
{ {
// offer --> ACCOUNT --> account // offer --> ACCOUNT --> account
// Note: offer is always deliver/redeeming as account is issuer. // Note: offer is always deliver/redeeming as account is issuer.
Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> account"));
// deliver -> redeem // deliver -> redeem
if (bRedeem // Allowed to redeem. if (bRedeem // Allowed to redeem.
@@ -2772,6 +2863,8 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
{ {
// offer --> ACCOUNT --> offer // offer --> ACCOUNT --> offer
// deliver/redeem -> deliver/issue. // deliver/redeem -> deliver/issue.
Log(lsINFO) << str(boost::format("calcNodeAccountRev: offer --> ACCOUNT --> offer"));
if (bIssue // Allowed to issue. if (bIssue // Allowed to issue.
&& saCurDeliverReq != saCurDeliverAct) // Can only if issue if more can not be redeemed. && saCurDeliverReq != saCurDeliverAct) // Can only if issue if more can not be redeemed.
{ {
@@ -2821,14 +2914,14 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
// For bNxtAccount // For bNxtAccount
const STAmount& saPrvRedeemReq = prvPN.saFwdRedeem; const STAmount& saPrvRedeemReq = prvPN.saFwdRedeem;
STAmount saPrvRedeemAct; STAmount saPrvRedeemAct(saPrvRedeemReq.getCurrency());
const STAmount& saPrvIssueReq = prvPN.saFwdIssue; const STAmount& saPrvIssueReq = prvPN.saFwdIssue;
STAmount saPrvIssueAct; STAmount saPrvIssueAct(saPrvIssueReq.getCurrency());
// For !bPrvAccount // For !bPrvAccount
const STAmount& saPrvDeliverReq = prvPN.saRevDeliver; const STAmount& saPrvDeliverReq = prvPN.saRevDeliver;
STAmount saPrvDeliverAct; STAmount saPrvDeliverAct(saPrvDeliverReq.getCurrency());
// For bNxtAccount // For bNxtAccount
const STAmount& saCurRedeemReq = curPN.saRevRedeem; const STAmount& saCurRedeemReq = curPN.saRevRedeem;
@@ -2843,6 +2936,16 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
STAmount& saCurReceive = pspCur->saOutAct; STAmount& saCurReceive = pspCur->saOutAct;
Log(lsINFO) << str(boost::format("calcNodeAccountFwd> uIndex=%d/%d saCurRedeemReq=%s/%s saCurIssueReq=%s/%s saCurDeliverReq=%s/%s")
% uIndex
% uLast
% saCurRedeemReq.getText()
% saCurRedeemReq.getHumanCurrency()
% saCurIssueReq.getText()
% saCurIssueReq.getHumanCurrency()
% saCurDeliverReq.getText()
% saCurDeliverReq.getHumanCurrency());
// Ripple through account. // Ripple through account.
if (bPrvAccount && bNxtAccount) if (bPrvAccount && bNxtAccount)
@@ -2860,26 +2963,49 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
STAmount& saCurIssueReq = curPN.saRevIssue; STAmount& saCurIssueReq = curPN.saRevIssue;
STAmount& saCurIssueAct = curPN.saFwdIssue; STAmount& saCurIssueAct = curPN.saFwdIssue;
STAmount& saCurSendMaxReq = pspCur->saInReq; STAmount& saCurSendMaxReq = pspCur->saInReq; // Negative for no limit, doing a calculation.
STAmount& saCurSendMaxAct = pspCur->saInAct; STAmount& saCurSendMaxAct = pspCur->saInAct; // Report to user how much this sends.
if (saCurRedeemReq) if (saCurRedeemReq)
{ {
// Redeem requested. // Redeem requested.
saCurRedeemAct = MIN(saCurRedeemAct, saCurSendMaxReq); saCurRedeemAct = saCurRedeemReq.isNegative()
saCurSendMaxAct = saCurRedeemAct; ? saCurRedeemReq
: MIN(saCurRedeemReq, saCurSendMaxReq);
} }
else
{
saCurRedeemAct = STAmount(saCurRedeemReq);
}
saCurSendMaxAct = saCurRedeemAct;
if (saCurIssueReq && saCurSendMaxReq != saCurRedeemAct) if (saCurIssueReq && (saCurSendMaxReq.isNegative() || saCurSendMaxReq != saCurRedeemAct))
{ {
// Issue requested and not over budget. // Issue requested and not over budget.
saCurIssueAct = MIN(saCurSendMaxReq-saCurRedeemAct, saCurIssueReq); saCurIssueAct = saCurSendMaxReq.isNegative()
// saCurSendMaxAct += saCurIssueReq; // Not needed. ? saCurIssueReq
: MIN(saCurSendMaxReq-saCurRedeemAct, saCurIssueReq);
} }
else
{
saCurIssueAct = STAmount(saCurIssueReq);
}
saCurSendMaxAct += saCurIssueAct;
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: ^ --> ACCOUNT --> account : saCurSendMaxReq=%s saCurRedeemAct=%s saCurIssueReq=%s saCurIssueAct=%s")
% saCurSendMaxReq.getFullText()
% saCurRedeemAct.getFullText()
% saCurIssueReq.getFullText()
% saCurIssueAct.getFullText());
} }
else if (uIndex == uLast) else if (uIndex == uLast)
{ {
// account --> ACCOUNT --> $ // account --> ACCOUNT --> $
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s")
% NewcoinAddress::createHumanAccountID(uPrvAccountID)
% NewcoinAddress::createHumanAccountID(uCurAccountID)
% saPrvRedeemReq.getFullText()
% saPrvIssueReq.getFullText());
// Last node. Accept all funds. Calculate amount actually to credit. // Last node. Accept all funds. Calculate amount actually to credit.
@@ -2891,11 +3017,12 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
saCurReceive = saPrvRedeemReq+saIssueCrd; saCurReceive = saPrvRedeemReq+saIssueCrd;
// Actually receive. // Actually receive.
rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq+saPrvIssueReq); rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq+saPrvIssueReq, false);
} }
else else
{ {
// account --> ACCOUNT --> account // account --> ACCOUNT --> account
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> account"));
// Previous redeem part 1: redeem -> redeem // Previous redeem part 1: redeem -> redeem
if (bRedeem // Can redeem. if (bRedeem // Can redeem.
@@ -2936,12 +3063,13 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
// Adjust prv --> cur balance : take all inbound // Adjust prv --> cur balance : take all inbound
// XXX Currency must be in amount. // XXX Currency must be in amount.
rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq); rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq, false);
} }
} }
else if (bPrvAccount && !bNxtAccount) else if (bPrvAccount && !bNxtAccount)
{ {
// account --> ACCOUNT --> offer // account --> ACCOUNT --> offer
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> offer"));
// redeem -> issue. // redeem -> issue.
// wants to redeem and current would and can issue. // wants to redeem and current would and can issue.
@@ -2962,13 +3090,14 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
// Adjust prv --> cur balance : take all inbound // Adjust prv --> cur balance : take all inbound
// XXX Currency must be in amount. // XXX Currency must be in amount.
rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq); rippleCredit(uPrvAccountID, uCurAccountID, saPrvRedeemReq + saPrvIssueReq, false);
} }
else if (!bPrvAccount && bNxtAccount) else if (!bPrvAccount && bNxtAccount)
{ {
if (uIndex == uLast) if (uIndex == uLast)
{ {
// offer --> ACCOUNT --> $ // offer --> ACCOUNT --> $
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $"));
// Amount to credit. // Amount to credit.
saCurReceive = saPrvDeliverAct; saCurReceive = saPrvDeliverAct;
@@ -2978,6 +3107,7 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
else else
{ {
// offer --> ACCOUNT --> account // offer --> ACCOUNT --> account
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> account"));
// deliver -> redeem // deliver -> redeem
if (bRedeem // Allowed to redeem. if (bRedeem // Allowed to redeem.
@@ -3005,6 +3135,8 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
{ {
// offer --> ACCOUNT --> offer // offer --> ACCOUNT --> offer
// deliver/redeem -> deliver/issue. // deliver/redeem -> deliver/issue.
Log(lsINFO) << str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> offer"));
if (bIssue // Allowed to issue. if (bIssue // Allowed to issue.
&& saPrvDeliverReq // Previous wants to deliver && saPrvDeliverReq // Previous wants to deliver
&& saCurIssueReq) // Current wants issue. && saCurIssueReq) // Current wants issue.
@@ -3134,6 +3266,8 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
pnCur.uAccountID = uAccountID; pnCur.uAccountID = uAccountID;
pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID; pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID;
pnCur.uIssuerID = bIssuer ? uIssuerID : uAccountID; pnCur.uIssuerID = bIssuer ? uIssuerID : uAccountID;
pnCur.saRevRedeem = STAmount(uCurrencyID);
pnCur.saRevIssue = STAmount(uCurrencyID);
if (!bFirst) if (!bFirst)
{ {
@@ -3144,6 +3278,40 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
!!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as issuer. !!pnCur.uCurrencyID ? uAccountID : ACCOUNT_XNS); // Account as issuer.
} }
if (bValid && !vpnNodes.empty())
{
const paymentNode& pnBck = vpnNodes.back();
bool bBckAccount = !!(pnBck.uFlags & STPathElement::typeAccount);
if (bBckAccount)
{
SLE::pointer sleRippleState = mLedger->getSLE(Ledger::getRippleStateIndex(pnBck.uAccountID, pnCur.uAccountID, pnPrv.uCurrencyID));
if (!sleRippleState)
{
Log(lsINFO) << "pushNode: No credit line between "
<< NewcoinAddress::createHumanAccountID(pnBck.uAccountID)
<< " and "
<< NewcoinAddress::createHumanAccountID(pnCur.uAccountID)
<< " for "
<< STAmount::createHumanCurrency(pnPrv.uCurrencyID)
<< "." ;
bValid = false;
}
else
{
Log(lsINFO) << "pushNode: Credit line found between "
<< NewcoinAddress::createHumanAccountID(pnBck.uAccountID)
<< " and "
<< NewcoinAddress::createHumanAccountID(pnCur.uAccountID)
<< " for "
<< STAmount::createHumanCurrency(pnPrv.uCurrencyID)
<< "." ;
}
}
}
if (bValid) if (bValid)
vpnNodes.push_back(pnCur); vpnNodes.push_back(pnCur);
} }
@@ -3187,11 +3355,11 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
if (bValid) if (bValid)
{ {
// Verify that previous account is allowed to issue. // Verify that previous account is allowed to issue.
const paymentNode& pnLst = vpnNodes.back(); const paymentNode& pnBck = vpnNodes.back();
bool bLstAccount = !!(pnLst.uFlags & STPathElement::typeAccount); bool bBckAccount = !!(pnBck.uFlags & STPathElement::typeAccount);
bool bLstIssue = !!(pnLst.uFlags & STPathElement::typeIssue); bool bBckIssue = !!(pnBck.uFlags & STPathElement::typeIssue);
if (bLstAccount && !bLstIssue) if (bBckAccount && !bBckIssue)
{ {
Log(lsINFO) << "pushNode: previous account must be allowed to issue."; Log(lsINFO) << "pushNode: previous account must be allowed to issue.";
@@ -3210,6 +3378,7 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
// XXX Disallow loops in ripple paths // XXX Disallow loops in ripple paths
PathState::PathState( PathState::PathState(
Ledger::pointer lpLedger,
int iIndex, int iIndex,
const LedgerEntrySet& lesSource, const LedgerEntrySet& lesSource,
const STPath& spSourcePath, const STPath& spSourcePath,
@@ -3219,7 +3388,7 @@ PathState::PathState(
STAmount saSendMax, STAmount saSendMax,
bool bPartialPayment bool bPartialPayment
) )
: mIndex(iIndex), uQuality(0) : mLedger(lpLedger), mIndex(iIndex), uQuality(0)
{ {
uint160 uInCurrencyID = saSendMax.getCurrency(); uint160 uInCurrencyID = saSendMax.getCurrency();
uint160 uOutCurrencyID = saSend.getCurrency(); uint160 uOutCurrencyID = saSend.getCurrency();
@@ -3231,6 +3400,7 @@ PathState::PathState(
saInReq = saSendMax; saInReq = saSendMax;
saOutReq = saSend; saOutReq = saSend;
// Push sending node.
bValid = pushNode( bValid = pushNode(
STPathElement::typeAccount STPathElement::typeAccount
| STPathElement::typeRedeem | STPathElement::typeRedeem
@@ -3276,13 +3446,16 @@ Json::Value PathState::getJson() const
{ {
Json::Value jvNode(Json::objectValue); Json::Value jvNode(Json::objectValue);
Json::Value jvFlags(Json::objectValue); Json::Value jvFlags(Json::arrayValue);
if (pnNode.uFlags & STPathElement::typeAccount)
jvFlags.append("account");
if (pnNode.uFlags & STPathElement::typeRedeem) if (pnNode.uFlags & STPathElement::typeRedeem)
jvFlags["redeem"] = 1; jvFlags.append("redeem");
if (pnNode.uFlags & STPathElement::typeIssue) if (pnNode.uFlags & STPathElement::typeIssue)
jvFlags["issue"] = 1; jvFlags.append("issue");
jvNode["flags"] = jvFlags; jvNode["flags"] = jvFlags;
@@ -3295,6 +3468,24 @@ Json::Value PathState::getJson() const
if (!!pnNode.uIssuerID) if (!!pnNode.uIssuerID)
jvNode["issuer"] = NewcoinAddress::createHumanAccountID(pnNode.uIssuerID); jvNode["issuer"] = NewcoinAddress::createHumanAccountID(pnNode.uIssuerID);
// if (!!pnNode.saRevRedeem)
jvNode["rev_redeem"] = pnNode.saRevRedeem.getFullText();
// if (!!pnNode.saRevIssue)
jvNode["rev_issue"] = pnNode.saRevIssue.getFullText();
// if (!!pnNode.saRevDeliver)
jvNode["rev_deliver"] = pnNode.saRevDeliver.getFullText();
// if (!!pnNode.saFwdRedeem)
jvNode["fwd_redeem"] = pnNode.saFwdRedeem.getFullText();
// if (!!pnNode.saFwdIssue)
jvNode["fwd_issue"] = pnNode.saFwdIssue.getFullText();
// if (!!pnNode.saFwdDeliver)
jvNode["fwd_deliver"] = pnNode.saFwdDeliver.getFullText();
jvNodes.append(jvNode); jvNodes.append(jvNode);
} }
@@ -3323,7 +3514,7 @@ Json::Value PathState::getJson() const
// Calculate a node and its previous nodes. // Calculate a node and its previous nodes.
// From the destination work towards the source calculating how much must be asked for. // From the destination work towards the source calculating how much must be asked for.
// --> bAllowPartial: If false, fail if can't meet requirements. // --> bAllowPartial: If false, fail if can't meet requirements.
// <-- bSuccess: true=success, false=insufficient funds / liqudity. // <-- bValid: true=success, false=insufficient funds / liqudity.
// <-> pnNodes: // <-> pnNodes:
// --> [end]saWanted.mAmount // --> [end]saWanted.mAmount
// --> [all]saWanted.mCurrency // --> [all]saWanted.mCurrency
@@ -3334,28 +3525,28 @@ bool TransactionEngine::calcNode(unsigned int uIndex, PathState::pointer pspCur,
{ {
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& curPN = pspCur->vpnNodes[uIndex];
bool bCurAccount = !!(curPN.uFlags & STPathElement::typeAccount); bool bCurAccount = !!(curPN.uFlags & STPathElement::typeAccount);
bool bSuccess; bool bValid;
// Do current node reverse. // Do current node reverse.
bSuccess = bCurAccount bValid = bCurAccount
? calcNodeAccountRev(uIndex, pspCur, bMultiQuality) ? calcNodeAccountRev(uIndex, pspCur, bMultiQuality)
: calcNodeOfferRev(uIndex, pspCur, bMultiQuality); : calcNodeOfferRev(uIndex, pspCur, bMultiQuality);
// Do previous. // Do previous.
if (bSuccess && uIndex) if (bValid && uIndex)
{ {
bSuccess = calcNode(uIndex-1, pspCur, bMultiQuality); bValid = calcNode(uIndex-1, pspCur, bMultiQuality);
} }
// Do current node forward. // Do current node forward.
if (bSuccess) if (bValid)
{ {
bSuccess = bCurAccount bValid = bCurAccount
? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality) ? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality)
: calcNodeOfferFwd(uIndex, pspCur, bMultiQuality); : calcNodeOfferFwd(uIndex, pspCur, bMultiQuality);
} }
return bSuccess; return bValid;
} }
// Calculate the next increment of a path. // Calculate the next increment of a path.
@@ -3372,9 +3563,14 @@ void TransactionEngine::pathNext(PathState::pointer pspCur, int iPaths)
assert(pspCur->vpnNodes.size() >= 2); assert(pspCur->vpnNodes.size() >= 2);
bool bZero = !calcNode(uLast, pspCur, iPaths == 1); bool bValid = calcNode(uLast, pspCur, iPaths == 1);
pspCur->uQuality = bZero Log(lsINFO) << "pathNext: bValid="
<< bValid
<< " saOutAct=" << pspCur->saOutAct.getText()
<< " saInAct=" << pspCur->saInAct.getText();
pspCur->uQuality = bValid
? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality. ? STAmount::getRate(pspCur->saOutAct, pspCur->saInAct) // Calculate relative quality.
: 0; // Mark path as inactive. : 0; // Mark path as inactive.
@@ -3591,6 +3787,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
// Direct path. // Direct path.
Log(lsINFO) << "doPayment: Build direct:"; Log(lsINFO) << "doPayment: Build direct:";
vpsPaths.push_back(PathState::createPathState( vpsPaths.push_back(PathState::createPathState(
mLedger,
vpsPaths.size(), vpsPaths.size(),
mNodes, mNodes,
STPath(), STPath(),
@@ -3606,6 +3803,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
{ {
Log(lsINFO) << "doPayment: Build path:"; Log(lsINFO) << "doPayment: Build path:";
vpsPaths.push_back(PathState::createPathState( vpsPaths.push_back(PathState::createPathState(
mLedger,
vpsPaths.size(), vpsPaths.size(),
mNodes, mNodes,
spPath, spPath,
@@ -3671,9 +3869,19 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
} }
} }
Log(lsINFO) << "doPayment: Delay transaction: No ripple paths could be satisfied."; std::string strToken;
std::string strHuman;
return terBAD_RIPPLE; if (transResultInfo(terResult, strToken, strHuman))
{
Log(lsINFO) << str(boost::format("doPayment: %s: %s") % strToken % strHuman);
}
else
{
assert(false);
}
return terResult;
} }
TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn) TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn)

View File

@@ -104,7 +104,7 @@ typedef struct {
uint16 uFlags; // --> From path. uint16 uFlags; // --> From path.
uint160 uAccountID; // --> Recieving/sending account. uint160 uAccountID; // --> Recieving/sending account.
uint160 uCurrencyID; // --> Currency to recieve. uint160 uCurrencyID; // --> Accounts: receive and send, Offers: send.
// --- For offer's next has currency out. // --- For offer's next has currency out.
uint160 uIssuerID; // --> Currency's issuer uint160 uIssuerID; // --> Currency's issuer
@@ -125,6 +125,8 @@ typedef struct {
class PathState class PathState
{ {
protected: protected:
Ledger::pointer mLedger;
bool pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID); bool pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
bool pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID); bool pushImply(uint160 uAccountID, uint160 uCurrencyID, uint160 uIssuerID);
@@ -143,6 +145,7 @@ public:
STAmount saOutAct; // Amount actually sent (calc output). STAmount saOutAct; // Amount actually sent (calc output).
PathState( PathState(
Ledger::pointer lpLedger,
int iIndex, int iIndex,
const LedgerEntrySet& lesSource, const LedgerEntrySet& lesSource,
const STPath& spSourcePath, const STPath& spSourcePath,
@@ -156,6 +159,7 @@ public:
Json::Value getJson() const; Json::Value getJson() const;
static PathState::pointer createPathState( static PathState::pointer createPathState(
Ledger::pointer lpLedger,
int iIndex, int iIndex,
const LedgerEntrySet& lesSource, const LedgerEntrySet& lesSource,
const STPath& spSourcePath, const STPath& spSourcePath,
@@ -165,7 +169,7 @@ public:
STAmount saSendMax, STAmount saSendMax,
bool bPartialPayment bool bPartialPayment
) )
{ return boost::make_shared<PathState>(iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); }; { return boost::make_shared<PathState>(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); };
static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs); static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs);
}; };
@@ -225,7 +229,7 @@ protected:
STAmount rippleHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID); 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 rippleTransfer(const uint160& uSenderID, const uint160& uReceiverID, const uint160& uIssuerID, const STAmount& saAmount);
void rippleCredit(const uint160& uSenderID, const uint160& uReceiverID, 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); STAmount rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount);
STAmount accountHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID); STAmount accountHolds(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID);