Merge branch 'ripple'

This commit is contained in:
Arthur Britto
2012-08-19 21:37:22 -07:00
4 changed files with 244 additions and 208 deletions

View File

@@ -1315,9 +1315,9 @@ Json::Value RPCServer::doPeers(const Json::Value& params)
} }
// ripple <regular_seed> <paying_account> // ripple <regular_seed> <paying_account>
// <source_max> <source_currency> <source_issuerID> [noredeem] [noissue] // <source_max> <source_currency> [<source_issuerID>] // XXX [noredeem] [noissue]
// <path>+ // <path>+
// full|partial <dest_account> <dest_amount> <dest_currency> <dest_issuerID> // full|partial <dest_account> <dest_amount> <dest_currency> [<dest_issuerID>]
// //
// path: // path:
// path <path_element>+ // path <path_element>+
@@ -1331,6 +1331,7 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
STAmount saSrcAmountMax; STAmount saSrcAmountMax;
uint160 uSrcCurrencyID; uint160 uSrcCurrencyID;
NewcoinAddress naSrcAccountID; NewcoinAddress naSrcAccountID;
NewcoinAddress naSrcIssuerID;
bool bSrcRedeem = true; bool bSrcRedeem = true;
bool bSrcIssue = true; bool bSrcIssue = true;
bool bPartial; bool bPartial;
@@ -1338,11 +1339,12 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
NewcoinAddress naDstAccountID; NewcoinAddress naDstAccountID;
STAmount saDstAmount; STAmount saDstAmount;
uint160 uDstCurrencyID; uint160 uDstCurrencyID;
NewcoinAddress naDstIssuerID;
std::vector<paymentNode> vpnPath; std::vector<paymentNode> vpnPath;
STPathSet spsPaths; STPathSet spsPaths;
naSrcIssuerID.setAccountID(params[4u].asString()); // <source_issuerID>
if (!naSeed.setSeedGeneric(params[0u].asString())) // <regular_seed> if (!naSeed.setSeedGeneric(params[0u].asString())) // <regular_seed>
{ {
return RPCError(rpcBAD_SEED); return RPCError(rpcBAD_SEED);
@@ -1351,13 +1353,18 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
{ {
return RPCError(rpcSRC_ACT_MALFORMED); return RPCError(rpcSRC_ACT_MALFORMED);
} }
// <source_max> <source_currency> <source_issuerID> // <source_max> <source_currency> [<source_issuerID>]
else if (!saSrcAmountMax.setFullValue(params[2u].asString(), params[3u].asString(), params[4u].asString())) else if (!saSrcAmountMax.setFullValue(params[2u].asString(), params[3u].asString(), params[naSrcIssuerID.isValid() ? 4u : 1u].asString()))
{ {
// Log(lsINFO) << "naSrcIssuerID.isValid(): " << naSrcIssuerID.isValid();
// Log(lsINFO) << "source_max: " << params[2u].asString();
// Log(lsINFO) << "source_currency: " << params[3u].asString();
// Log(lsINFO) << "source_issuer: " << params[naSrcIssuerID.isValid() ? 4u : 2u].asString();
return RPCError(rpcSRC_AMT_MALFORMED); return RPCError(rpcSRC_AMT_MALFORMED);
} }
int iArg = 5; int iArg = 4 + naSrcIssuerID.isValid();
if (params[iArg].asString() == "noredeem") // [noredeem] if (params[iArg].asString() == "noredeem") // [noredeem]
{ {
@@ -1483,14 +1490,21 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
{ {
return RPCError(rpcDST_ACT_MALFORMED); return RPCError(rpcDST_ACT_MALFORMED);
} }
const unsigned int uDstIssuer = params.size() == iArg + 3 ? iArg+2 : iArg-1;
// <dest_amount> <dest_currency> <dest_issuerID> // <dest_amount> <dest_currency> <dest_issuerID>
else if (params.size() != iArg + 3 || !saDstAmount.setFullValue(params[iArg].asString(), params[iArg+1].asString(), params[iArg+2].asString())) if (params.size() != iArg + 2 && params.size() != iArg + 3)
{ {
Log(lsINFO) << "params.size(): " << params.size(); // Log(lsINFO) << "params.size(): " << params.size();
Log(lsINFO) << " iArg: " << iArg;
Log(lsINFO) << " Amount: " << params[iArg].asString(); return RPCError(rpcDST_AMT_MALFORMED);
Log(lsINFO) << "Currency: " << params[iArg+1].asString(); }
Log(lsINFO) << " Issuer: " << params[iArg+2].asString(); else if (!saDstAmount.setFullValue(params[iArg].asString(), params[iArg+1].asString(), params[uDstIssuer].asString()))
{
// Log(lsINFO) << " Amount: " << params[iArg].asString();
// Log(lsINFO) << "Currency: " << params[iArg+1].asString();
// Log(lsINFO) << " Issuer: " << params[uDstIssuer].asString();
return RPCError(rpcDST_AMT_MALFORMED); return RPCError(rpcDST_AMT_MALFORMED);
} }
@@ -1515,6 +1529,8 @@ Json::Value RPCServer::doRipple(const Json::Value &params)
// YYY Limit paths length and count. // YYY Limit paths length and count.
if (!asDst) if (!asDst)
{ {
Log(lsINFO) << "naDstAccountID: " << naDstAccountID.humanAccountID();
return RPCError(rpcDST_ACT_MISSING); return RPCError(rpcDST_ACT_MISSING);
} }
@@ -2526,7 +2542,7 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
{ "password_fund", &RPCServer::doPasswordFund, 2, 3, false, optCurrent }, { "password_fund", &RPCServer::doPasswordFund, 2, 3, false, optCurrent },
{ "password_set", &RPCServer::doPasswordSet, 2, 3, false, optNetwork }, { "password_set", &RPCServer::doPasswordSet, 2, 3, false, optNetwork },
{ "peers", &RPCServer::doPeers, 0, 0, true }, { "peers", &RPCServer::doPeers, 0, 0, true },
{ "ripple", &RPCServer::doRipple, 10, -1, false, optCurrent|optClosed }, { "ripple", &RPCServer::doRipple, 8, -1, false, optCurrent|optClosed },
{ "ripple_lines_get", &RPCServer::doRippleLinesGet, 1, 2, false, optCurrent }, { "ripple_lines_get", &RPCServer::doRippleLinesGet, 1, 2, false, optCurrent },
{ "ripple_line_set", &RPCServer::doRippleLineSet, 4, 7, false, optCurrent }, { "ripple_line_set", &RPCServer::doRippleLineSet, 4, 7, false, optCurrent },
{ "send", &RPCServer::doSend, 3, 7, false, optCurrent }, { "send", &RPCServer::doSend, 3, 7, false, optCurrent },

View File

@@ -5,6 +5,7 @@
#include "SerializedTypes.h" #include "SerializedTypes.h"
#include "SerializedObject.h" #include "SerializedObject.h"
#include "TransactionFormats.h" #include "TransactionFormats.h"
#include "Log.h"
#include "NewcoinAddress.h" #include "NewcoinAddress.h"
#include "utils.h" #include "utils.h"
@@ -308,7 +309,11 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name)
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary) if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
{ {
if (path.empty()) if (path.empty())
{
Log(lsINFO) << "STPathSet: Empty path.";
throw std::runtime_error("empty path"); throw std::runtime_error("empty path");
}
paths.push_back(path); paths.push_back(path);
path.clear(); path.clear();
@@ -320,13 +325,15 @@ STPathSet* STPathSet::construct(SerializerIterator& s, const char *name)
} }
else if (iType & ~STPathElement::typeValidBits) else if (iType & ~STPathElement::typeValidBits)
{ {
Log(lsINFO) << "STPathSet: Bad path element: " << iType;
throw std::runtime_error("bad path element"); throw std::runtime_error("bad path element");
} }
else else
{ {
bool bAccount = !!(iType & STPathElement::typeAccount); const bool bAccount = !!(iType & STPathElement::typeAccount);
bool bCurrency = !!(iType & STPathElement::typeCurrency); const bool bCurrency = !!(iType & STPathElement::typeCurrency);
bool bIssuer = !!(iType & STPathElement::typeIssuer); const bool bIssuer = !!(iType & STPathElement::typeIssuer);
uint160 uAccountID; uint160 uAccountID;
uint160 uCurrency; uint160 uCurrency;

View File

@@ -367,7 +367,7 @@ void TransactionEngine::rippleCredit(const uint160& uSenderID, const uint160& uR
STAmount TransactionEngine::rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount) STAmount TransactionEngine::rippleSend(const uint160& uSenderID, const uint160& uReceiverID, const STAmount& saAmount)
{ {
STAmount saActual; STAmount saActual;
uint160 uIssuerID = saAmount.getIssuer(); const uint160 uIssuerID = saAmount.getIssuer();
if (uSenderID == uIssuerID || uReceiverID == uIssuerID) if (uSenderID == uIssuerID || uReceiverID == uIssuerID)
{ {
@@ -1504,15 +1504,14 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti
return terNO_DST; return terNO_DST;
} }
bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest. const bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest.
bool bLimitAmount = txn.getITFieldPresent(sfLimitAmount); const bool bLimitAmount = txn.getITFieldPresent(sfLimitAmount);
STAmount saLimitAmount = bLimitAmount ? txn.getITFieldAmount(sfLimitAmount) : STAmount(); const STAmount saLimitAmount = bLimitAmount ? txn.getITFieldAmount(sfLimitAmount) : STAmount();
bool bQualityIn = txn.getITFieldPresent(sfQualityIn); const bool bQualityIn = txn.getITFieldPresent(sfQualityIn);
uint32 uQualityIn = bQualityIn ? txn.getITFieldU32(sfQualityIn) : 0; const uint32 uQualityIn = bQualityIn ? txn.getITFieldU32(sfQualityIn) : 0;
bool bQualityOut = txn.getITFieldPresent(sfQualityOut); const bool bQualityOut = txn.getITFieldPresent(sfQualityOut);
uint32 uQualityOut = bQualityIn ? txn.getITFieldU32(sfQualityOut) : 0; const uint32 uQualityOut = bQualityIn ? txn.getITFieldU32(sfQualityOut) : 0;
uint160 uCurrencyID = saLimitAmount.getCurrency(); const uint160 uCurrencyID = saLimitAmount.getCurrency();
STAmount saBalance(uCurrencyID);
bool bDelIndex = false; bool bDelIndex = false;
SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID)); SLE::pointer sleRippleState = entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID));
@@ -1620,9 +1619,9 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
{ {
std::cerr << "doNicknameSet>" << std::endl; std::cerr << "doNicknameSet>" << std::endl;
uint256 uNickname = txn.getITFieldH256(sfNickname); const uint256 uNickname = txn.getITFieldH256(sfNickname);
bool bMinOffer = txn.getITFieldPresent(sfMinimumOffer); const bool bMinOffer = txn.getITFieldPresent(sfMinimumOffer);
STAmount saMinOffer = bMinOffer ? txn.getITFieldAmount(sfAmount) : STAmount(); const STAmount saMinOffer = bMinOffer ? txn.getITFieldAmount(sfAmount) : STAmount();
SLE::pointer sleNickname = entryCache(ltNICKNAME, uNickname); SLE::pointer sleNickname = entryCache(ltNICKNAME, uNickname);
@@ -1631,7 +1630,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
// Edit old entry. // Edit old entry.
sleNickname->setIFieldAccount(sfAccount, mTxnAccountID); sleNickname->setIFieldAccount(sfAccount, mTxnAccountID);
if (bMinOffer && !saMinOffer.isZero()) if (bMinOffer && !!saMinOffer)
{ {
sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer); sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer);
} }
@@ -1653,7 +1652,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac
sleNickname->setIFieldAccount(sfAccount, mTxnAccountID); sleNickname->setIFieldAccount(sfAccount, mTxnAccountID);
if (bMinOffer && !saMinOffer.isZero()) if (bMinOffer && !!saMinOffer)
sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer); sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer);
} }
@@ -1666,7 +1665,7 @@ TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransa
{ {
std::cerr << "doPasswordFund>" << std::endl; std::cerr << "doPasswordFund>" << std::endl;
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); const uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
SLE::pointer sleDst = mTxnAccountID == uDstAccountID SLE::pointer sleDst = mTxnAccountID == uDstAccountID
? mTxnAccount ? mTxnAccount
: entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID)); : entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
@@ -1903,28 +1902,28 @@ bool TransactionEngine::calcNodeOfferRev(
{ {
bool bSuccess = false; bool bSuccess = false;
paymentNode& prvPN = pspCur->vpnNodes[uIndex-1]; paymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& pnCur = pspCur->vpnNodes[uIndex];
paymentNode& nxtPN = pspCur->vpnNodes[uIndex+1]; paymentNode& pnNxt = pspCur->vpnNodes[uIndex+1];
uint160& uPrvCurrencyID = prvPN.uCurrencyID; const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
uint160& uPrvIssuerID = prvPN.uIssuerID; const uint160& uPrvIssuerID = pnPrv.uIssuerID;
uint160& uCurCurrencyID = curPN.uCurrencyID; const uint160& uCurCurrencyID = pnCur.uCurrencyID;
uint160& uCurIssuerID = curPN.uIssuerID; const uint160& uCurIssuerID = pnCur.uIssuerID;
uint160& uNxtCurrencyID = nxtPN.uCurrencyID; const uint160& uNxtCurrencyID = pnNxt.uCurrencyID;
uint160& uNxtIssuerID = nxtPN.uIssuerID; const uint160& uNxtIssuerID = pnNxt.uIssuerID;
uint160& uNxtAccountID = nxtPN.uAccountID; const uint160& uNxtAccountID = pnNxt.uAccountID;
STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9); const STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9);
uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID); uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID);
uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip); const uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip);
bool bAdvance = !entryCache(ltDIR_NODE, uDirectTip); bool bAdvance = !entryCache(ltDIR_NODE, uDirectTip);
STAmount& saPrvDlvReq = prvPN.saRevDeliver; // To be adjusted. STAmount& saPrvDlvReq = pnPrv.saRevDeliver; // To be adjusted.
STAmount saPrvDlvAct; STAmount saPrvDlvAct;
const STAmount& saCurDlvReq = curPN.saRevDeliver; // Reverse driver. const STAmount& saCurDlvReq = pnCur.saRevDeliver; // Reverse driver.
STAmount saCurDlvAct; STAmount saCurDlvAct;
while (!!uDirectTip // Have a quality. while (!!uDirectTip // Have a quality.
@@ -1944,6 +1943,7 @@ bool TransactionEngine::calcNodeOfferRev(
{ {
// Do a directory. // Do a directory.
// - Drive on computing saCurDlvAct to derive saPrvDlvAct. // - Drive on computing saCurDlvAct to derive saPrvDlvAct.
// XXX Behave well, if entry type is wrong (someone beat us to using the hash)
SLE::pointer sleDirectDir = entryCache(ltDIR_NODE, uDirectTip); SLE::pointer sleDirectDir = entryCache(ltDIR_NODE, uDirectTip);
STAmount saOfrRate = STAmount::setRate(Ledger::getQuality(uDirectTip), uCurCurrencyID); // For correct ratio STAmount saOfrRate = STAmount::setRate(Ledger::getQuality(uDirectTip), uCurCurrencyID); // For correct ratio
unsigned int uEntry = 0; unsigned int uEntry = 0;
@@ -1969,14 +1969,14 @@ bool TransactionEngine::calcNodeOfferRev(
if (!saCurOfrFunds) if (!saCurOfrFunds)
{ {
// Offer is unfunded. // Offer is unfunded.
Log(lsINFO) << "calcNodeOffer: encountered unfunded offer"; Log(lsINFO) << "calcNodeOfferRev: encountered unfunded offer";
// XXX Mark unfunded. // XXX Mark unfunded.
} }
else if (sleCurOfr->getIFieldPresent(sfExpiration) && sleCurOfr->getIFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC()) else if (sleCurOfr->getIFieldPresent(sfExpiration) && sleCurOfr->getIFieldU32(sfExpiration) <= mLedger->getParentCloseTimeNC())
{ {
// Offer is expired. // Offer is expired.
Log(lsINFO) << "calcNodeOffer: encountered expired offer"; Log(lsINFO) << "calcNodeOfferRev: encountered expired offer";
// XXX Mark unfunded. // XXX Mark unfunded.
} }
@@ -2095,28 +2095,28 @@ bool TransactionEngine::calcNodeOfferFwd(
{ {
bool bSuccess = false; bool bSuccess = false;
paymentNode& prvPN = pspCur->vpnNodes[uIndex-1]; paymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& pnCur = pspCur->vpnNodes[uIndex];
paymentNode& nxtPN = pspCur->vpnNodes[uIndex+1]; paymentNode& pnNxt = pspCur->vpnNodes[uIndex+1];
uint160& uPrvCurrencyID = prvPN.uCurrencyID; const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
uint160& uPrvIssuerID = prvPN.uIssuerID; const uint160& uPrvIssuerID = pnPrv.uIssuerID;
uint160& uCurCurrencyID = curPN.uCurrencyID; const uint160& uCurCurrencyID = pnCur.uCurrencyID;
uint160& uCurIssuerID = curPN.uIssuerID; const uint160& uCurIssuerID = pnCur.uIssuerID;
uint160& uNxtCurrencyID = nxtPN.uCurrencyID; const uint160& uNxtCurrencyID = pnNxt.uCurrencyID;
uint160& uNxtIssuerID = nxtPN.uIssuerID; const uint160& uNxtIssuerID = pnNxt.uIssuerID;
uint160& uNxtAccountID = nxtPN.uAccountID; const uint160& uNxtAccountID = pnNxt.uAccountID;
STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9); const STAmount saTransferRate = STAmount(CURRENCY_ONE, rippleTransferRate(uCurIssuerID), -9);
uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID); uint256 uDirectTip = Ledger::getBookBase(uPrvCurrencyID, uPrvIssuerID, uCurCurrencyID, uCurIssuerID);
uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip); const uint256 uDirectEnd = Ledger::getQualityNext(uDirectTip);
bool bAdvance = !entryCache(ltDIR_NODE, uDirectTip); bool bAdvance = !entryCache(ltDIR_NODE, uDirectTip);
STAmount& saPrvDlvReq = prvPN.saFwdDeliver; // Forward driver. const STAmount& saPrvDlvReq = pnPrv.saFwdDeliver; // Forward driver.
STAmount saPrvDlvAct; STAmount saPrvDlvAct;
STAmount& saCurDlvReq = curPN.saFwdDeliver; STAmount& saCurDlvReq = pnCur.saFwdDeliver;
STAmount saCurDlvAct; STAmount saCurDlvAct;
while (!!uDirectTip // Have a quality. while (!!uDirectTip // Have a quality.
@@ -2163,22 +2163,22 @@ bool TransactionEngine::calcNodeOfferFwd(
{ {
// Next is an account. // Next is an account.
STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtAccountID == uCurIssuerID const STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtAccountID == uCurIssuerID
? saOne ? saOne
: saTransferRate; : saTransferRate;
bool bFee = saFeeRate != saOne; const bool bFee = saFeeRate != saOne;
STAmount saOutPass = STAmount::divide(saCurOfrInReq, saOfrRate, uCurCurrencyID); const STAmount saOutPass = STAmount::divide(saCurOfrInReq, saOfrRate, uCurCurrencyID);
STAmount saOutBase = MIN(saCurOfrOutReq, saOutPass); // Limit offer out by needed. const STAmount saOutBase = MIN(saCurOfrOutReq, saOutPass); // Limit offer out by needed.
STAmount saOutCost = MIN( const STAmount saOutCost = MIN(
bFee bFee
? STAmount::multiply(saOutBase, saFeeRate, uCurCurrencyID) ? STAmount::multiply(saOutBase, saFeeRate, uCurCurrencyID)
: saOutBase, : saOutBase,
saCurOfrFunds); // Limit cost by fees & funds. saCurOfrFunds); // Limit cost by fees & funds.
STAmount saOutDlvAct = bFee const STAmount saOutDlvAct = bFee
? STAmount::divide(saOutCost, saFeeRate, uCurCurrencyID) ? STAmount::divide(saOutCost, saFeeRate, uCurCurrencyID)
: saOutCost; // Out amount after fees. : saOutCost; // Out amount after fees.
STAmount saInDlvAct = STAmount::multiply(saOutDlvAct, saOfrRate, uCurCurrencyID); // Compute input w/o fees required. const STAmount saInDlvAct = STAmount::multiply(saOutDlvAct, saOfrRate, uCurCurrencyID); // Compute input w/o fees required.
saCurDlvAct += saOutDlvAct; // Portion of driver served. saCurDlvAct += saOutDlvAct; // Portion of driver served.
saPrvDlvAct += saInDlvAct; // Portion needed in previous. saPrvDlvAct += saInDlvAct; // Portion needed in previous.
@@ -2188,7 +2188,7 @@ bool TransactionEngine::calcNodeOfferFwd(
// Next is an offer. // Next is an offer.
uint256 uNxtTip = Ledger::getBookBase(uCurCurrencyID, uCurIssuerID, uNxtCurrencyID, uNxtIssuerID); uint256 uNxtTip = Ledger::getBookBase(uCurCurrencyID, uCurIssuerID, uNxtCurrencyID, uNxtIssuerID);
uint256 uNxtEnd = Ledger::getQualityNext(uNxtTip); const uint256 uNxtEnd = Ledger::getQualityNext(uNxtTip);
bool bNxtAdvance = !entryCache(ltDIR_NODE, uNxtTip); bool bNxtAdvance = !entryCache(ltDIR_NODE, uNxtTip);
while (!!uNxtTip // Have a quality. while (!!uNxtTip // Have a quality.
@@ -2217,30 +2217,30 @@ bool TransactionEngine::calcNodeOfferFwd(
{ {
// YYY This could combine offers with the same fee before doing math. // YYY This could combine offers with the same fee before doing math.
SLE::pointer sleNxtOfr = entryCache(ltOFFER, uNxtIndex); SLE::pointer sleNxtOfr = entryCache(ltOFFER, uNxtIndex);
uint160 uNxtOfrAccountID = sleNxtOfr->getIValueFieldAccount(sfAccount).getAccountID(); const uint160 uNxtOfrAccountID = sleNxtOfr->getIValueFieldAccount(sfAccount).getAccountID();
STAmount saNxtOfrIn = sleNxtOfr->getIValueFieldAmount(sfTakerPays); STAmount saNxtOfrIn = sleNxtOfr->getIValueFieldAmount(sfTakerPays);
// XXX Move issuer into STAmount // XXX Move issuer into STAmount
if (sleNxtOfr->getIFieldPresent(sfPaysIssuer)) if (sleNxtOfr->getIFieldPresent(sfPaysIssuer))
saNxtOfrIn.setIssuer(sleCurOfr->getIValueFieldAccount(sfPaysIssuer).getAccountID()); saNxtOfrIn.setIssuer(sleCurOfr->getIValueFieldAccount(sfPaysIssuer).getAccountID());
STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtOfrAccountID == uCurIssuerID const STAmount saFeeRate = uCurOfrAccountID == uCurIssuerID || uNxtOfrAccountID == uCurIssuerID
? saOne ? saOne
: saTransferRate; : saTransferRate;
bool bFee = saFeeRate != saOne; const bool bFee = saFeeRate != saOne;
STAmount saInBase = saCurOfrInReq-saCurOfrInAct; const STAmount saInBase = saCurOfrInReq-saCurOfrInAct;
STAmount saOutPass = STAmount::divide(saInBase, saOfrRate, uCurCurrencyID); const STAmount saOutPass = STAmount::divide(saInBase, saOfrRate, uCurCurrencyID);
STAmount saOutBase = MIN(saCurOfrOutReq, saOutPass); // Limit offer out by needed. STAmount saOutBase = MIN(saCurOfrOutReq, saOutPass); // Limit offer out by needed.
saOutBase = MIN(saOutBase, saNxtOfrIn); // Limit offer out by supplying offer. saOutBase = MIN(saOutBase, saNxtOfrIn); // Limit offer out by supplying offer.
STAmount saOutCost = MIN( const STAmount saOutCost = MIN(
bFee bFee
? STAmount::multiply(saOutBase, saFeeRate, uCurCurrencyID) ? STAmount::multiply(saOutBase, saFeeRate, uCurCurrencyID)
: saOutBase, : saOutBase,
saCurOfrFunds); // Limit cost by fees & funds. saCurOfrFunds); // Limit cost by fees & funds.
STAmount saOutDlvAct = bFee const STAmount saOutDlvAct = bFee
? STAmount::divide(saOutCost, saFeeRate, uCurCurrencyID) ? STAmount::divide(saOutCost, saFeeRate, uCurCurrencyID)
: saOutCost; // Out amount after fees. : saOutCost; // Out amount after fees.
STAmount saInDlvAct = STAmount::multiply(saOutDlvAct, saOfrRate, uPrvCurrencyID); // Compute input w/o fees required. const STAmount saInDlvAct = STAmount::multiply(saOutDlvAct, saOfrRate, uPrvCurrencyID); // Compute input w/o fees required.
saCurOfrInAct += saOutDlvAct; // Portion of driver served. saCurOfrInAct += saOutDlvAct; // Portion of driver served.
saPrvDlvAct += saOutDlvAct; // Portion needed in previous. saPrvDlvAct += saOutDlvAct; // Portion needed in previous.
@@ -2525,9 +2525,9 @@ void TransactionEngine::calcNodeRipple(
assert(saPrvReq.getCurrency() == saCurReq.getCurrency()); assert(saPrvReq.getCurrency() == saCurReq.getCurrency());
bool bPrvUnlimited = saPrvReq.isNegative(); const bool bPrvUnlimited = saPrvReq.isNegative();
STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct; const STAmount saPrv = bPrvUnlimited ? STAmount(saPrvReq) : saPrvReq-saPrvAct;
STAmount saCur = saCurReq-saCurAct; const STAmount saCur = saCurReq-saCurAct;
#if 0 #if 0
Log(lsINFO) << str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s") Log(lsINFO) << str(boost::format("calcNodeRipple: bPrvUnlimited=%d saPrv=%s saCur=%s")
@@ -2587,24 +2587,24 @@ Log(lsINFO) << str(boost::format("calcNodeRipple:4: saCurReq=%s") % saCurReq.get
bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality) bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality)
{ {
bool bSuccess = true; bool bSuccess = true;
unsigned int uLast = pspCur->vpnNodes.size() - 1; const unsigned int uLast = pspCur->vpnNodes.size() - 1;
paymentNode& prvPN = pspCur->vpnNodes[uIndex ? uIndex-1 : 0]; paymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& pnCur = pspCur->vpnNodes[uIndex];
paymentNode& nxtPN = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1]; paymentNode& pnNxt = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1];
bool bRedeem = !!(curPN.uFlags & STPathElement::typeRedeem); const bool bRedeem = !!(pnCur.uFlags & STPathElement::typeRedeem);
bool bPrvRedeem = !!(prvPN.uFlags & STPathElement::typeRedeem); const bool bPrvRedeem = !!(pnPrv.uFlags & STPathElement::typeRedeem);
bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue); const bool bIssue = !!(pnCur.uFlags & STPathElement::typeIssue);
bool bPrvIssue = !!(prvPN.uFlags & STPathElement::typeIssue); const bool bPrvIssue = !!(pnPrv.uFlags & STPathElement::typeIssue);
bool bPrvAccount = !uIndex || !!(prvPN.uFlags & STPathElement::typeAccount); const bool bPrvAccount = !uIndex || !!(pnPrv.uFlags & STPathElement::typeAccount);
bool bNxtAccount = uIndex == uLast || !!(nxtPN.uFlags & STPathElement::typeAccount); const bool bNxtAccount = uIndex == uLast || !!(pnNxt.uFlags & STPathElement::typeAccount);
const uint160& uPrvAccountID = prvPN.uAccountID; const uint160& uPrvAccountID = pnPrv.uAccountID;
const uint160& uCurAccountID = curPN.uAccountID; const uint160& uCurAccountID = pnCur.uAccountID;
const uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue. const uint160& uNxtAccountID = bNxtAccount ? pnNxt.uAccountID : uCurAccountID; // Offers are always issue.
const uint160& uCurrencyID = curPN.uCurrencyID; const uint160& uCurrencyID = pnCur.uCurrencyID;
const uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 1; const uint32 uQualityIn = uIndex ? rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : 1;
const uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 1; const uint32 uQualityOut = uIndex != uLast ? rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : 1;
@@ -2614,24 +2614,24 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
const STAmount saPrvLimit = uIndex && bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID); const STAmount saPrvLimit = uIndex && bPrvAccount ? rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID) : STAmount(uCurrencyID);
const 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 = pnPrv.saRevRedeem;
const STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID); const STAmount saPrvIssueReq = bPrvIssue ? saPrvLimit - saPrvBalance : STAmount(uCurrencyID);
STAmount& saPrvIssueAct = prvPN.saRevIssue; STAmount& saPrvIssueAct = pnPrv.saRevIssue;
// For !bPrvAccount // For !bPrvAccount
const STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited. const STAmount saPrvDeliverReq = STAmount(uCurrencyID, -1); // Unlimited.
STAmount& saPrvDeliverAct = prvPN.saRevDeliver; STAmount& saPrvDeliverAct = pnPrv.saRevDeliver;
// For bNxtAccount // For bNxtAccount
const STAmount& saCurRedeemReq = curPN.saRevRedeem; const STAmount& saCurRedeemReq = pnCur.saRevRedeem;
STAmount saCurRedeemAct(saCurRedeemReq.getCurrency()); STAmount saCurRedeemAct(saCurRedeemReq.getCurrency());
const STAmount& saCurIssueReq = curPN.saRevIssue; const STAmount& saCurIssueReq = pnCur.saRevIssue;
STAmount saCurIssueAct(saCurIssueReq.getCurrency()); // Track progress. STAmount saCurIssueAct(saCurIssueReq.getCurrency()); // Track progress.
// For !bNxtAccount // For !bNxtAccount
const STAmount& saCurDeliverReq = curPN.saRevDeliver; const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
STAmount saCurDeliverAct(saCurDeliverReq.getCurrency()); STAmount saCurDeliverAct(saCurDeliverReq.getCurrency());
// For uIndex == uLast // For uIndex == uLast
@@ -2881,47 +2881,47 @@ bool TransactionEngine::calcNodeAccountRev(unsigned int uIndex, PathState::point
bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality) bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality)
{ {
bool bSuccess = true; bool bSuccess = true;
unsigned int uLast = pspCur->vpnNodes.size() - 1; const unsigned int uLast = pspCur->vpnNodes.size() - 1;
paymentNode& prvPN = pspCur->vpnNodes[uIndex ? uIndex-1 : 0]; paymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& pnCur = pspCur->vpnNodes[uIndex];
paymentNode& nxtPN = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1]; paymentNode& pnNxt = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1];
bool bRedeem = !!(curPN.uFlags & STPathElement::typeRedeem); const bool bRedeem = !!(pnCur.uFlags & STPathElement::typeRedeem);
bool bIssue = !!(curPN.uFlags & STPathElement::typeIssue); const bool bIssue = !!(pnCur.uFlags & STPathElement::typeIssue);
bool bPrvAccount = !!(prvPN.uFlags & STPathElement::typeAccount); const bool bPrvAccount = !!(pnPrv.uFlags & STPathElement::typeAccount);
bool bNxtAccount = !!(nxtPN.uFlags & STPathElement::typeAccount); const bool bNxtAccount = !!(pnNxt.uFlags & STPathElement::typeAccount);
uint160& uPrvAccountID = prvPN.uAccountID; const uint160& uPrvAccountID = pnPrv.uAccountID;
uint160& uCurAccountID = curPN.uAccountID; const uint160& uCurAccountID = pnCur.uAccountID;
uint160& uNxtAccountID = bNxtAccount ? nxtPN.uAccountID : uCurAccountID; // Offers are always issue. const uint160& uNxtAccountID = bNxtAccount ? pnNxt.uAccountID : uCurAccountID; // Offers are always issue.
uint160& uCurrencyID = curPN.uCurrencyID; const uint160& uCurrencyID = pnCur.uCurrencyID;
uint32 uQualityIn = rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID); uint32 uQualityIn = rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID);
uint32 uQualityOut = rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID); uint32 uQualityOut = rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID);
// For bNxtAccount // For bNxtAccount
const STAmount& saPrvRedeemReq = prvPN.saFwdRedeem; const STAmount& saPrvRedeemReq = pnPrv.saFwdRedeem;
STAmount saPrvRedeemAct(saPrvRedeemReq.getCurrency()); STAmount saPrvRedeemAct(saPrvRedeemReq.getCurrency());
const STAmount& saPrvIssueReq = prvPN.saFwdIssue; const STAmount& saPrvIssueReq = pnPrv.saFwdIssue;
STAmount saPrvIssueAct(saPrvIssueReq.getCurrency()); STAmount saPrvIssueAct(saPrvIssueReq.getCurrency());
// For !bPrvAccount // For !bPrvAccount
const STAmount& saPrvDeliverReq = prvPN.saRevDeliver; const STAmount& saPrvDeliverReq = pnPrv.saRevDeliver;
STAmount saPrvDeliverAct(saPrvDeliverReq.getCurrency()); STAmount saPrvDeliverAct(saPrvDeliverReq.getCurrency());
// For bNxtAccount // For bNxtAccount
const STAmount& saCurRedeemReq = curPN.saRevRedeem; const STAmount& saCurRedeemReq = pnCur.saRevRedeem;
STAmount& saCurRedeemAct = curPN.saFwdRedeem; STAmount& saCurRedeemAct = pnCur.saFwdRedeem;
const STAmount& saCurIssueReq = curPN.saRevIssue; const STAmount& saCurIssueReq = pnCur.saRevIssue;
STAmount& saCurIssueAct = curPN.saFwdIssue; STAmount& saCurIssueAct = pnCur.saFwdIssue;
// For !bNxtAccount // For !bNxtAccount
const STAmount& saCurDeliverReq = curPN.saRevDeliver; const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
STAmount& saCurDeliverAct = curPN.saFwdDeliver; STAmount& saCurDeliverAct = pnCur.saFwdDeliver;
STAmount& saCurReceive = pspCur->saOutAct; STAmount& saCurReceive = pspCur->saOutAct;
@@ -2945,14 +2945,14 @@ bool TransactionEngine::calcNodeAccountFwd(unsigned int uIndex, PathState::point
// First node, calculate amount to send. // First node, calculate amount to send.
// XXX Use stamp/ripple balance // XXX Use stamp/ripple balance
paymentNode& curPN = pspCur->vpnNodes[uIndex]; paymentNode& pnCur = pspCur->vpnNodes[uIndex];
STAmount& saCurRedeemReq = curPN.saRevRedeem; const STAmount& saCurRedeemReq = pnCur.saRevRedeem;
STAmount& saCurRedeemAct = curPN.saFwdRedeem; STAmount& saCurRedeemAct = pnCur.saFwdRedeem;
STAmount& saCurIssueReq = curPN.saRevIssue; const STAmount& saCurIssueReq = pnCur.saRevIssue;
STAmount& saCurIssueAct = curPN.saFwdIssue; STAmount& saCurIssueAct = pnCur.saFwdIssue;
STAmount& saCurSendMaxReq = pspCur->saInReq; // Negative for no limit, doing a calculation. const STAmount& saCurSendMaxReq = pspCur->saInReq; // Negative for no limit, doing a calculation.
STAmount& saCurSendMaxAct = pspCur->saInAct; // Report to user how much this sends. STAmount& saCurSendMaxAct = pspCur->saInAct; // Report to user how much this sends.
if (saCurRedeemReq) if (saCurRedeemReq)
@@ -3224,18 +3224,18 @@ bool PathState::pushNode(int iType, uint160 uAccountID, uint160 uCurrencyID, uin
<< " " << STAmount::createHumanCurrency(uCurrencyID) << " " << STAmount::createHumanCurrency(uCurrencyID)
<< " " << NewcoinAddress::createHumanAccountID(uIssuerID); << " " << NewcoinAddress::createHumanAccountID(uIssuerID);
paymentNode pnCur; paymentNode pnCur;
bool bFirst = vpnNodes.empty(); const bool bFirst = vpnNodes.empty();
const paymentNode& pnPrv = bFirst ? paymentNode() : vpnNodes.back(); const paymentNode& pnPrv = bFirst ? paymentNode() : vpnNodes.back();
// true, iff node is a ripple account. false, iff node is an offer node. // true, iff node is a ripple account. false, iff node is an offer node.
bool bAccount = !!(iType & STPathElement::typeAccount); const bool bAccount = !!(iType & STPathElement::typeAccount);
// true, iff currency supplied. // true, iff currency supplied.
// Currency is specified for the output of the current node. // Currency is specified for the output of the current node.
bool bCurrency = !!(iType & STPathElement::typeCurrency); const bool bCurrency = !!(iType & STPathElement::typeCurrency);
// Issuer is specified for the output of the current node. // Issuer is specified for the output of the current node.
bool bIssuer = !!(iType & STPathElement::typeIssuer); const bool bIssuer = !!(iType & STPathElement::typeIssuer);
// true, iff account is allowed to redeem it's IOUs to next node. // true, iff account is allowed to redeem it's IOUs to next node.
bool bRedeem = !!(iType & STPathElement::typeRedeem); const bool bRedeem = !!(iType & STPathElement::typeRedeem);
bool bIssue = !!(iType & STPathElement::typeIssue); const bool bIssue = !!(iType & STPathElement::typeIssue);
bool bValid = true; bool bValid = true;
pnCur.uFlags = iType; pnCur.uFlags = iType;
@@ -3379,10 +3379,10 @@ PathState::PathState(
) )
: mLedger(lpLedger), mIndex(iIndex), uQuality(0) : mLedger(lpLedger), mIndex(iIndex), uQuality(0)
{ {
uint160 uInCurrencyID = saSendMax.getCurrency(); const uint160 uInCurrencyID = saSendMax.getCurrency();
uint160 uOutCurrencyID = saSend.getCurrency(); const uint160 uOutCurrencyID = saSend.getCurrency();
uint160 uInIssuerID = !!uInCurrencyID ? uSenderID : ACCOUNT_XNS; const uint160 uInIssuerID = !!uInCurrencyID ? uSenderID : ACCOUNT_XNS;
uint160 uOutIssuerID = !!uOutCurrencyID ? uReceiverID : ACCOUNT_XNS; const uint160 uOutIssuerID = !!uOutCurrencyID ? uReceiverID : ACCOUNT_XNS;
lesEntries = lesSource.duplicate(); lesEntries = lesSource.duplicate();
@@ -3512,8 +3512,8 @@ Json::Value PathState::getJson() const
// XXX Disallow looping. // XXX Disallow looping.
bool TransactionEngine::calcNode(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality) bool TransactionEngine::calcNode(unsigned int uIndex, PathState::pointer pspCur, bool bMultiQuality)
{ {
paymentNode& curPN = pspCur->vpnNodes[uIndex]; const paymentNode& pnCur = pspCur->vpnNodes[uIndex];
bool bCurAccount = !!(curPN.uFlags & STPathElement::typeAccount); const bool bCurAccount = !!(pnCur.uFlags & STPathElement::typeAccount);
bool bValid; bool bValid;
// Do current node reverse. // Do current node reverse.
@@ -3570,17 +3570,17 @@ void TransactionEngine::pathNext(PathState::pointer pspCur, int iPaths)
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn) TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn)
{ {
// Ripple if source or destination is non-native or if there are paths. // Ripple if source or destination is non-native or if there are paths.
uint32 uTxFlags = txn.getFlags(); const uint32 uTxFlags = txn.getFlags();
bool bCreate = !!(uTxFlags & tfCreateAccount); const bool bCreate = !!(uTxFlags & tfCreateAccount);
bool bNoRippleDirect = !!(uTxFlags & tfNoRippleDirect); const bool bNoRippleDirect = !!(uTxFlags & tfNoRippleDirect);
bool bPartialPayment = !!(uTxFlags & tfPartialPayment); const bool bPartialPayment = !!(uTxFlags & tfPartialPayment);
bool bPaths = txn.getITFieldPresent(sfPaths); const bool bPaths = txn.getITFieldPresent(sfPaths);
bool bMax = txn.getITFieldPresent(sfSendMax); const bool bMax = txn.getITFieldPresent(sfSendMax);
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); const uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
STAmount saDstAmount = txn.getITFieldAmount(sfAmount); const STAmount saDstAmount = txn.getITFieldAmount(sfAmount);
STAmount saMaxAmount = bMax ? txn.getITFieldAmount(sfSendMax) : saDstAmount; const STAmount saMaxAmount = bMax ? txn.getITFieldAmount(sfSendMax) : saDstAmount;
uint160 uSrcCurrency = saMaxAmount.getCurrency(); const uint160 uSrcCurrency = saMaxAmount.getCurrency();
uint160 uDstCurrency = saDstAmount.getCurrency(); const uint160 uDstCurrency = saDstAmount.getCurrency();
if (!uDstAccountID) if (!uDstAccountID)
{ {
@@ -3774,8 +3774,10 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
if (!bNoRippleDirect) if (!bNoRippleDirect)
{ {
// Direct path. // Direct path.
// XXX Might also make a stamp bridge by default.
Log(lsINFO) << "doPayment: Build direct:"; Log(lsINFO) << "doPayment: Build direct:";
vpsPaths.push_back(PathState::createPathState(
PathState::pointer pspDirect = PathState::createPathState(
mLedger, mLedger,
vpsPaths.size(), vpsPaths.size(),
mNodes, mNodes,
@@ -3784,14 +3786,19 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
mTxnAccountID, mTxnAccountID,
saDstAmount, saDstAmount,
saMaxAmount, saMaxAmount,
bPartialPayment bPartialPayment);
));
if (pspDirect)
vpsPaths.push_back(pspDirect);
} }
Log(lsINFO) << "doPayment: Paths: " << spsPaths.getPathCount();
BOOST_FOREACH(const STPath& spPath, spsPaths) BOOST_FOREACH(const STPath& spPath, spsPaths)
{ {
Log(lsINFO) << "doPayment: Build path:"; Log(lsINFO) << "doPayment: Build path:";
vpsPaths.push_back(PathState::createPathState(
PathState::pointer pspExpanded = PathState::createPathState(
mLedger, mLedger,
vpsPaths.size(), vpsPaths.size(),
mNodes, mNodes,
@@ -3800,8 +3807,10 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
mTxnAccountID, mTxnAccountID,
saDstAmount, saDstAmount,
saMaxAmount, saMaxAmount,
bPartialPayment bPartialPayment);
));
if (pspExpanded)
vpsPaths.push_back(pspExpanded);
} }
TransactionEngineResult terResult; TransactionEngineResult terResult;
@@ -3877,11 +3886,11 @@ TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransacti
{ {
std::cerr << "WalletAdd>" << std::endl; std::cerr << "WalletAdd>" << std::endl;
std::vector<unsigned char> vucPubKey = txn.getITFieldVL(sfPubKey); const std::vector<unsigned char> vucPubKey = txn.getITFieldVL(sfPubKey);
std::vector<unsigned char> vucSignature = txn.getITFieldVL(sfSignature); const std::vector<unsigned char> vucSignature = txn.getITFieldVL(sfSignature);
uint160 uAuthKeyID = txn.getITFieldAccount(sfAuthorizedKey); const uint160 uAuthKeyID = txn.getITFieldAccount(sfAuthorizedKey);
NewcoinAddress naMasterPubKey = NewcoinAddress::createAccountPublic(vucPubKey); const NewcoinAddress naMasterPubKey = NewcoinAddress::createAccountPublic(vucPubKey);
uint160 uDstAccountID = naMasterPubKey.getAccountID(); const uint160 uDstAccountID = naMasterPubKey.getAccountID();
if (!naMasterPubKey.accountPublicVerify(Serializer::getSHA512Half(uAuthKeyID.begin(), uAuthKeyID.size()), vucSignature)) if (!naMasterPubKey.accountPublicVerify(Serializer::getSHA512Half(uAuthKeyID.begin(), uAuthKeyID.size()), vucSignature))
{ {
@@ -3957,12 +3966,12 @@ TransactionEngineResult TransactionEngine::takeOffers(
Log(lsINFO) << "takeOffers: against book: " << uBookBase.ToString(); Log(lsINFO) << "takeOffers: against book: " << uBookBase.ToString();
uint256 uTipIndex = uBookBase; uint256 uTipIndex = uBookBase;
uint256 uBookEnd = Ledger::getQualityNext(uBookBase); const uint256 uBookEnd = Ledger::getQualityNext(uBookBase);
uint64 uTakeQuality = STAmount::getRate(saTakerGets, saTakerPays); const uint64 uTakeQuality = STAmount::getRate(saTakerGets, saTakerPays);
uint160 uTakerPaysAccountID = saTakerPays.getIssuer(); const uint160 uTakerPaysAccountID = saTakerPays.getIssuer();
uint160 uTakerPaysCurrency = saTakerPays.getCurrency(); const uint160 uTakerPaysCurrency = saTakerPays.getCurrency();
uint160 uTakerGetsAccountID = saTakerGets.getIssuer(); const uint160 uTakerGetsAccountID = saTakerGets.getIssuer();
uint160 uTakerGetsCurrency = saTakerGets.getCurrency(); const uint160 uTakerGetsCurrency = saTakerGets.getCurrency();
TransactionEngineResult terResult = tenUNKNOWN; TransactionEngineResult terResult = tenUNKNOWN;
saTakerPaid = 0; saTakerPaid = 0;
@@ -4017,7 +4026,7 @@ TransactionEngineResult TransactionEngine::takeOffers(
Log(lsINFO) << "takeOffers: considering offer : " << sleOffer->getJson(0); Log(lsINFO) << "takeOffers: considering offer : " << sleOffer->getJson(0);
uint160 uOfferOwnerID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID(); const uint160 uOfferOwnerID = sleOffer->getIValueFieldAccount(sfAccount).getAccountID();
STAmount saOfferPays = sleOffer->getIValueFieldAmount(sfTakerGets); STAmount saOfferPays = sleOffer->getIValueFieldAmount(sfTakerGets);
STAmount saOfferGets = sleOffer->getIValueFieldAmount(sfTakerPays); STAmount saOfferGets = sleOffer->getIValueFieldAmount(sfTakerPays);
@@ -4138,28 +4147,28 @@ TransactionEngineResult TransactionEngine::takeOffers(
TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransaction& txn) TransactionEngineResult TransactionEngine::doOfferCreate(const SerializedTransaction& txn)
{ {
Log(lsWARNING) << "doOfferCreate> " << txn.getJson(0); Log(lsWARNING) << "doOfferCreate> " << txn.getJson(0);
uint32 txFlags = txn.getFlags(); const uint32 txFlags = txn.getFlags();
bool bPassive = !!(txFlags & tfPassive); const bool bPassive = !!(txFlags & tfPassive);
uint160 uPaysIssuerID = txn.getITFieldAccount(sfPaysIssuer); const uint160 uPaysIssuerID = txn.getITFieldAccount(sfPaysIssuer);
uint160 uGetsIssuerID = txn.getITFieldAccount(sfGetsIssuer); const uint160 uGetsIssuerID = txn.getITFieldAccount(sfGetsIssuer);
STAmount saTakerPays = txn.getITFieldAmount(sfTakerPays); STAmount saTakerPays = txn.getITFieldAmount(sfTakerPays);
saTakerPays.setIssuer(uPaysIssuerID); saTakerPays.setIssuer(uPaysIssuerID);
Log(lsWARNING) << "doOfferCreate: saTakerPays=" << saTakerPays.getFullText(); Log(lsWARNING) << "doOfferCreate: saTakerPays=" << saTakerPays.getFullText();
STAmount saTakerGets = txn.getITFieldAmount(sfTakerGets); STAmount saTakerGets = txn.getITFieldAmount(sfTakerGets);
saTakerGets.setIssuer(uGetsIssuerID); saTakerGets.setIssuer(uGetsIssuerID);
Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText(); Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
uint32 uExpiration = txn.getITFieldU32(sfExpiration); const uint32 uExpiration = txn.getITFieldU32(sfExpiration);
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration); const bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
uint32 uSequence = txn.getSequence(); const uint32 uSequence = txn.getSequence();
uint256 uLedgerIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence); const uint256 uLedgerIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
SLE::pointer sleOffer = entryCreate(ltOFFER, uLedgerIndex); SLE::pointer sleOffer = entryCreate(ltOFFER, uLedgerIndex);
Log(lsINFO) << "doOfferCreate: Creating offer node: " << uLedgerIndex.ToString() << " uSequence=" << uSequence; Log(lsINFO) << "doOfferCreate: Creating offer node: " << uLedgerIndex.ToString() << " uSequence=" << uSequence;
uint160 uPaysCurrency = saTakerPays.getCurrency(); const uint160 uPaysCurrency = saTakerPays.getCurrency();
uint160 uGetsCurrency = saTakerGets.getCurrency(); const uint160 uGetsCurrency = saTakerGets.getCurrency();
uint64 uRate = STAmount::getRate(saTakerGets, saTakerPays); const uint64 uRate = STAmount::getRate(saTakerGets, saTakerPays);
TransactionEngineResult terResult = terSUCCESS; TransactionEngineResult terResult = terSUCCESS;
uint256 uDirectory; // Delete hints. uint256 uDirectory; // Delete hints.
@@ -4225,7 +4234,7 @@ Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
{ {
STAmount saOfferPaid; STAmount saOfferPaid;
STAmount saOfferGot; STAmount saOfferGot;
uint256 uTakeBookBase = Ledger::getBookBase(uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID); const uint256 uTakeBookBase = Ledger::getBookBase(uGetsCurrency, uGetsIssuerID, uPaysCurrency, uPaysIssuerID);
Log(lsINFO) << str(boost::format("doOfferCreate: take against book: %s : %s/%s -> %s/%s") Log(lsINFO) << str(boost::format("doOfferCreate: take against book: %s : %s/%s -> %s/%s")
% uTakeBookBase.ToString() % uTakeBookBase.ToString()
@@ -4332,8 +4341,8 @@ Log(lsWARNING) << "doOfferCreate: saTakerGets=" << saTakerGets.getFullText();
TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransaction& txn) TransactionEngineResult TransactionEngine::doOfferCancel(const SerializedTransaction& txn)
{ {
TransactionEngineResult terResult; TransactionEngineResult terResult;
uint32 uSequence = txn.getITFieldU32(sfOfferSequence); const uint32 uSequence = txn.getITFieldU32(sfOfferSequence);
uint256 uOfferIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence); const uint256 uOfferIndex = Ledger::getOfferIndex(mTxnAccountID, uSequence);
SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex); SLE::pointer sleOffer = entryCache(ltOFFER, uOfferIndex);
if (sleOffer) if (sleOffer)

View File

@@ -169,7 +169,11 @@ public:
STAmount saSendMax, STAmount saSendMax,
bool bPartialPayment bool bPartialPayment
) )
{ return boost::make_shared<PathState>(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment); }; {
PathState::pointer pspNew = boost::make_shared<PathState>(lpLedger, iIndex, lesSource, spSourcePath, uReceiverID, uSenderID, saSend, saSendMax, bPartialPayment);
return pspNew && pspNew->bValid ? pspNew : PathState::pointer();
}
static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs); static bool lessPriority(const PathState::pointer& lhs, const PathState::pointer& rhs);
}; };