本文整理汇总了C++中STAmount::getCurrency方法的典型用法代码示例。如果您正苦于以下问题:C++ STAmount::getCurrency方法的具体用法?C++ STAmount::getCurrency怎么用?C++ STAmount::getCurrency使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类STAmount
的用法示例。
在下文中一共展示了STAmount::getCurrency方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: saLimitAmount
TER
SetTrust::preflight (PreflightContext const& ctx)
{
auto const ret = preflight1 (ctx);
if (!isTesSuccess (ret))
return ret;
auto& tx = ctx.tx;
auto& j = ctx.j;
std::uint32_t const uTxFlags = tx.getFlags ();
if (uTxFlags & tfTrustSetMask)
{
JLOG(j.trace) <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
STAmount const saLimitAmount (tx.getFieldAmount (sfLimitAmount));
if (!isLegalNet (saLimitAmount))
return temBAD_AMOUNT;
if (saLimitAmount.native ())
{
JLOG(j.trace) <<
"Malformed transaction: specifies native limit " <<
saLimitAmount.getFullText ();
return temBAD_LIMIT;
}
if (badCurrency() == saLimitAmount.getCurrency ())
{
JLOG(j.trace) <<
"Malformed transaction: specifies XRP as IOU";
return temBAD_CURRENCY;
}
if (saLimitAmount < zero)
{
JLOG(j.trace) <<
"Malformed transaction: Negative credit limit.";
return temBAD_LIMIT;
}
// Check if destination makes sense.
auto const& issuer = saLimitAmount.getIssuer ();
if (!issuer || issuer == noAccount())
{
JLOG(j.trace) <<
"Malformed transaction: no destination account.";
return temDST_NEEDED;
}
return preflight2 (ctx);
}
示例2: creditLimit
STAmount creditLimit (
LedgerEntrySet& ledger,
AccountID const& account,
AccountID const& issuer,
Currency const& currency)
{
STAmount result ({currency, account});
auto sleDivvyState = ledger.entryCache (ltRIPPLE_STATE,
getDivvyStateIndex (account, issuer, currency));
if (sleDivvyState)
{
result = sleDivvyState->getFieldAmount (
account < issuer ? sfLowLimit : sfHighLimit);
result.setIssuer (account);
}
assert (result.getIssuer () == account);
assert (result.getCurrency () == currency);
return result;
}
示例3: doApply
TER doApply () override
{
// Divvy if source or destination is non-native or if there are paths.
std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
bool const limitQuality = uTxFlags & tfLimitQuality;
bool const defaultPathsAllowed = !(uTxFlags & tfNoDivvyDirect);
bool const bPaths = mTxn.isFieldPresent (sfPaths);
bool const bMax = mTxn.isFieldPresent (sfSendMax);
AccountID const uDstAccountID (mTxn.getFieldAccount160 (sfDestination));
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
STAmount maxSourceAmount;
if (bMax)
maxSourceAmount = mTxn.getFieldAmount (sfSendMax);
else if (saDstAmount.native ())
maxSourceAmount = saDstAmount;
else
maxSourceAmount = STAmount (
{saDstAmount.getCurrency (), mTxnAccountID},
saDstAmount.mantissa(), saDstAmount.exponent (),
saDstAmount < zero);
m_journal.trace <<
"maxSourceAmount=" << maxSourceAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText ();
// Open a ledger for editing.
auto const index = getAccountRootIndex (uDstAccountID);
SLE::pointer sleDst (mEngine->view().entryCache (ltACCOUNT_ROOT, index));
if (!sleDst)
{
// Destination account does not exist.
if (!saDstAmount.native ())
{
m_journal.trace <<
"Delay transaction: Destination account does not exist.";
// Another transaction could create the account and then this
// transaction would succeed.
return tecNO_DST;
}
else if (mParams & tapOPEN_LEDGER && partialPaymentAllowed)
{
// You cannot fund an account with a partial payment.
// Make retry work smaller, by rejecting this.
m_journal.trace <<
"Delay transaction: Partial payment not allowed to create account.";
// Another transaction could create the account and then this
// transaction would succeed.
return telNO_DST_PARTIAL;
}
else if (saDstAmount < STAmount (mEngine->getLedger ()->getReserve (0)))
{
// getReserve() is the minimum amount that an account can have.
// Reserve is not scaled by load.
m_journal.trace <<
"Delay transaction: Destination account does not exist. " <<
"Insufficent payment to create account.";
// TODO: dedupe
// Another transaction could create the account and then this
// transaction would succeed.
return tecNO_DST_INSUF_XDV;
}
// Create the account.
sleDst = std::make_shared<SLE>(ltACCOUNT_ROOT,
getAccountRootIndex (uDstAccountID));
sleDst->setFieldAccount (sfAccount, uDstAccountID);
sleDst->setFieldU32 (sfSequence, 1);
mEngine->view().entryCreate(sleDst);
}
else if ((sleDst->getFlags () & lsfRequireDestTag) &&
!mTxn.isFieldPresent (sfDestinationTag))
{
// The tag is basically account-specific information we don't
// understand, but we can require someone to fill it in.
// We didn't make this test for a newly-formed account because there's
// no way for this field to be set.
m_journal.trace << "Malformed transaction: DestinationTag required.";
return tecDST_TAG_NEEDED;
}
else
{
// Tell the engine that we are intending to change the the destination
// account. The source account gets always charged a fee so it's always
// marked as modified.
mEngine->view().entryModify (sleDst);
}
TER terResult;
bool const bDivvy = bPaths || bMax || !saDstAmount.native ();
// XXX Should bMax be sufficient to imply divvy?
//.........这里部分代码省略.........
示例4: doApply
TER TrustSetTransactor::doApply ()
{
TER terResult = tesSUCCESS;
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet>";
const STAmount saLimitAmount = mTxn.getFieldAmount (sfLimitAmount);
const bool bQualityIn = mTxn.isFieldPresent (sfQualityIn);
const bool bQualityOut = mTxn.isFieldPresent (sfQualityOut);
const uint160 uCurrencyID = saLimitAmount.getCurrency ();
uint160 uDstAccountID = saLimitAmount.getIssuer ();
const bool bHigh = mTxnAccountID > uDstAccountID; // true, iff current is high account.
uint32 uQualityIn = bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0;
uint32 uQualityOut = bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0;
if (!saLimitAmount.isLegalNet ())
return temBAD_AMOUNT;
if (bQualityIn && QUALITY_ONE == uQualityIn)
uQualityIn = 0;
if (bQualityOut && QUALITY_ONE == uQualityOut)
uQualityOut = 0;
const uint32 uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfTrustSetMask)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
const bool bSetAuth = isSetBit (uTxFlags, tfSetfAuth);
const bool bSetNoRipple = isSetBit (uTxFlags, tfSetNoRipple);
const bool bClearNoRipple = isSetBit (uTxFlags, tfClearNoRipple);
if (bSetAuth && !isSetBit (mTxnAccount->getFieldU32 (sfFlags), lsfRequireAuth))
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Retry: Auth not required.";
return tefNO_AUTH_REQUIRED;
}
if (saLimitAmount.isNative ())
{
WriteLog (lsINFO, TrustSetTransactor) << boost::str (boost::format ("doTrustSet: Malformed transaction: Native credit limit: %s")
% saLimitAmount.getFullText ());
return temBAD_LIMIT;
}
if (saLimitAmount.isNegative ())
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Negative credit limit.";
return temBAD_LIMIT;
}
// Check if destination makes sense.
if (!uDstAccountID || uDstAccountID == ACCOUNT_ONE)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Destination account not specified.";
return temDST_NEEDED;
}
if (mTxnAccountID == uDstAccountID)
{
SLE::pointer selDelete = mEngine->entryCache (ltRIPPLE_STATE, Ledger::getRippleStateIndex (mTxnAccountID, uDstAccountID, uCurrencyID));
if (selDelete)
{
WriteLog (lsWARNING, TrustSetTransactor) << "doTrustSet: Clearing redundant line.";
return mEngine->getNodes ().trustDelete (selDelete, mTxnAccountID, uDstAccountID);
}
else
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Malformed transaction: Can not extend credit to self.";
return temDST_IS_SRC;
}
}
SLE::pointer sleDst = mEngine->entryCache (ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID));
if (!sleDst)
{
WriteLog (lsINFO, TrustSetTransactor) << "doTrustSet: Delay transaction: Destination account does not exist.";
return tecNO_DST;
}
const uint32 uOwnerCount = mTxnAccount->getFieldU32 (sfOwnerCount);
// The reserve required to create the line.
const uint64 uReserveCreate = (uOwnerCount < 2) ? 0 : mEngine->getLedger ()->getReserve (uOwnerCount + 1);
STAmount saLimitAllow = saLimitAmount;
saLimitAllow.setIssuer (mTxnAccountID);
//.........这里部分代码省略.........
示例5: bPassive
TER
CreateOffer::doApply ()
{
if (m_journal.debug) m_journal.debug <<
"OfferCreate> " << mTxn.getJson (0);
std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const bPassive (uTxFlags & tfPassive);
bool const bImmediateOrCancel (uTxFlags & tfImmediateOrCancel);
bool const bFillOrKill (uTxFlags & tfFillOrKill);
bool const bSell (uTxFlags & tfSell);
STAmount saTakerPays = mTxn.getFieldAmount (sfTakerPays);
STAmount saTakerGets = mTxn.getFieldAmount (sfTakerGets);
if (!saTakerPays.isLegalNet () || !saTakerGets.isLegalNet ())
return temBAD_AMOUNT;
auto const& uPaysIssuerID = saTakerPays.getIssuer ();
auto const& uPaysCurrency = saTakerPays.getCurrency ();
auto const& uGetsIssuerID = saTakerGets.getIssuer ();
auto const& uGetsCurrency = saTakerGets.getCurrency ();
bool const bHaveExpiration (mTxn.isFieldPresent (sfExpiration));
bool const bHaveCancel (mTxn.isFieldPresent (sfOfferSequence));
std::uint32_t const uExpiration = mTxn.getFieldU32 (sfExpiration);
std::uint32_t const uCancelSequence = mTxn.getFieldU32 (sfOfferSequence);
// FIXME understand why we use SequenceNext instead of current transaction
// sequence to determine the transaction. Why is the offer seuqnce
// number insufficient?
std::uint32_t const uAccountSequenceNext = mTxnAccount->getFieldU32 (sfSequence);
std::uint32_t const uSequence = mTxn.getSequence ();
const uint256 uLedgerIndex = Ledger::getOfferIndex (mTxnAccountID, uSequence);
if (m_journal.debug)
{
m_journal.debug <<
"Creating offer node: " << to_string (uLedgerIndex) <<
" uSequence=" << uSequence;
if (bImmediateOrCancel)
m_journal.debug << "Transaction: IoC set.";
if (bFillOrKill)
m_journal.debug << "Transaction: FoK set.";
}
// This is the original rate of this offer, and is the rate at which it will
// be placed, even if crossing offers change the amounts.
std::uint64_t const uRate = STAmount::getRate (saTakerGets, saTakerPays);
TER terResult (tesSUCCESS);
// This is the ledger view that we work against. Transactions are applied
// as we go on processing transactions.
core::LedgerView& view (mEngine->view ());
// This is a checkpoint with just the fees paid. If something goes wrong
// with this transaction, we roll back to this ledger.
core::LedgerView view_checkpoint (view);
view.bumpSeq (); // Begin ledger variance.
SLE::pointer sleCreator = mEngine->entryCache (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (mTxnAccountID));
if (uTxFlags & tfOfferCreateMask)
{
if (m_journal.debug) m_journal.debug <<
"Malformed transaction: Invalid flags set.";
terResult = temINVALID_FLAG;
}
else if (bImmediateOrCancel && bFillOrKill)
{
if (m_journal.debug) m_journal.debug <<
"Malformed transaction: both IoC and FoK set.";
terResult = temINVALID_FLAG;
}
else if (bHaveExpiration && !uExpiration)
{
m_journal.warning <<
"Malformed offer: bad expiration";
terResult = temBAD_EXPIRATION;
}
else if (saTakerPays.isNative () && saTakerGets.isNative ())
{
m_journal.warning <<
"Malformed offer: XRP for XRP";
terResult = temBAD_OFFER;
}
//.........这里部分代码省略.........
示例6: doRipplePathFind
// This interface is deprecated.
Json::Value doRipplePathFind (RPC::Context& context)
{
RPC::LegacyPathFind lpf (context.role == Role::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
context.loadType = Resource::feeHighBurdenRPC;
RippleAddress raSrc;
RippleAddress raDst;
STAmount saDstAmount;
Ledger::pointer lpLedger;
Json::Value jvResult;
if (getConfig().RUN_STANDALONE ||
context.params.isMember(jss::ledger) ||
context.params.isMember(jss::ledger_index) ||
context.params.isMember(jss::ledger_hash))
{
// The caller specified a ledger
jvResult = RPC::lookupLedger (
context.params, lpLedger, context.netOps);
if (!lpLedger)
return jvResult;
}
if (!context.params.isMember ("source_account"))
{
jvResult = rpcError (rpcSRC_ACT_MISSING);
}
else if (!context.params["source_account"].isString ()
|| !raSrc.setAccountID (
context.params["source_account"].asString ()))
{
jvResult = rpcError (rpcSRC_ACT_MALFORMED);
}
else if (!context.params.isMember ("destination_account"))
{
jvResult = rpcError (rpcDST_ACT_MISSING);
}
else if (!context.params["destination_account"].isString ()
|| !raDst.setAccountID (
context.params["destination_account"].asString ()))
{
jvResult = rpcError (rpcDST_ACT_MALFORMED);
}
else if (
// Parse saDstAmount.
!context.params.isMember ("destination_amount")
|| ! amountFromJsonNoThrow(saDstAmount, context.params["destination_amount"])
|| saDstAmount <= zero
|| (!isXRP(saDstAmount.getCurrency ())
&& (!saDstAmount.getIssuer () ||
noAccount() == saDstAmount.getIssuer ())))
{
WriteLog (lsINFO, RPCHandler) << "Bad destination_amount.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else if (
// Checks on source_currencies.
context.params.isMember ("source_currencies")
&& (!context.params["source_currencies"].isArray ()
|| !context.params["source_currencies"].size ())
// Don't allow empty currencies.
)
{
WriteLog (lsINFO, RPCHandler) << "Bad source_currencies.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else
{
context.loadType = Resource::feeHighBurdenRPC;
RippleLineCache::pointer cache;
if (lpLedger)
{
// The caller specified a ledger
lpLedger = std::make_shared<Ledger> (std::ref (*lpLedger), false);
cache = std::make_shared<RippleLineCache>(lpLedger);
}
else
{
// The closed ledger is recent and any nodes made resident
// have the best chance to persist
lpLedger = context.netOps.getClosedLedger();
cache = getApp().getPathRequests().getLineCache(lpLedger, false);
}
Json::Value jvSrcCurrencies;
if (context.params.isMember ("source_currencies"))
{
jvSrcCurrencies = context.params["source_currencies"];
}
else
{
auto currencies = accountSourceCurrencies (raSrc, cache, true);
jvSrcCurrencies = Json::Value (Json::arrayValue);
//.........这里部分代码省略.........
示例7: takeOffers
// Take as much as possible. Adjusts account balances. Charges fees on top to taker.
// --> uBookBase: The order book to take against.
// --> saTakerPays: What the taker offers (w/ issuer)
// --> saTakerGets: What the taker wanted (w/ issuer)
// <-- saTakerPaid: What taker could have paid including saved not including fees. To reduce an offer.
// <-- saTakerGot: What taker got not including fees. To reduce an offer.
// <-- terResult: tesSUCCESS, terNO_ACCOUNT, telFAILED_PROCESSING, or tecFAILED_PROCESSING
// <-- bUnfunded: if tesSUCCESS, consider offer unfunded after taking.
TER OfferCreateTransactor::takeOffers (
const bool bOpenLedger,
const bool bPassive,
const bool bSell,
uint256 const& uBookBase,
const uint160& uTakerAccountID,
SLE::ref sleTakerAccount,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
STAmount& saTakerPaid,
STAmount& saTakerGot,
bool& bUnfunded)
{
// The book has the most elements. Take the perspective of the book.
// Book is ordered for taker: taker pays / taker gets (smaller is better)
// The order is for the other books currencys for get and pays are opposites.
// We want the same ratio for the respective currencies.
// So we swap paid and gets for determing take quality.
assert (saTakerPays && saTakerGets);
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: bSell: " << bSell << ": against book: " << uBookBase.ToString ();
LedgerEntrySet& lesActive = mEngine->getNodes ();
uint256 uTipIndex = uBookBase;
const uint256 uBookEnd = Ledger::getQualityNext (uBookBase);
const uint64 uTakeQuality = STAmount::getRate (saTakerGets, saTakerPays);
STAmount saTakerRate = STAmount::setRate (uTakeQuality);
const uint160 uTakerPaysAccountID = saTakerPays.getIssuer ();
const uint160 uTakerGetsAccountID = saTakerGets.getIssuer ();
TER terResult = temUNCERTAIN;
boost::unordered_set<uint256> usOfferUnfundedBecame; // Offers that became unfunded.
boost::unordered_set<uint160> usAccountTouched; // Accounts touched.
saTakerPaid = STAmount (saTakerPays.getCurrency (), saTakerPays.getIssuer ());
saTakerGot = STAmount (saTakerGets.getCurrency (), saTakerGets.getIssuer ());
bUnfunded = false;
while (temUNCERTAIN == terResult)
{
SLE::pointer sleOfferDir;
uint64 uTipQuality = 0;
STAmount saTakerFunds = lesActive.accountFunds (uTakerAccountID, saTakerPays);
STAmount saSubTakerPays = saTakerPays - saTakerPaid; // How much more to spend.
STAmount saSubTakerGets = saTakerGets - saTakerGot; // How much more is wanted.
// Figure out next offer to take, if needed.
if (saTakerFunds.isPositive () // Taker has funds available.
&& saSubTakerPays.isPositive ()
&& saSubTakerGets.isPositive ())
{
sleOfferDir = mEngine->entryCache (ltDIR_NODE, lesActive.getNextLedgerIndex (uTipIndex, uBookEnd));
if (sleOfferDir)
{
uTipIndex = sleOfferDir->getIndex ();
uTipQuality = Ledger::getQuality (uTipIndex);
WriteLog (lsDEBUG, OfferCreateTransactor) << boost::str (boost::format ("takeOffers: possible counter offer found: uTipQuality=%d uTipIndex=%s")
% uTipQuality
% uTipIndex.ToString ());
}
else
{
WriteLog (lsTRACE, OfferCreateTransactor) << "takeOffers: counter offer book is empty: "
<< uTipIndex.ToString ()
<< " ... "
<< uBookEnd.ToString ();
}
}
if (!saTakerFunds.isPositive ()) // Taker has no funds.
{
// Done. Ran out of funds on previous round. As fees aren't calculated directly in this routine, funds are checked here.
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: done: taker unfunded.";
bUnfunded = true; // Don't create an order.
terResult = tesSUCCESS;
}
else if (!sleOfferDir // No offer directory to take.
|| uTakeQuality < uTipQuality // No offers of sufficient quality available.
|| (bPassive && uTakeQuality == uTipQuality))
{
// Done.
STAmount saTipRate = sleOfferDir ? STAmount::setRate (uTipQuality) : saTakerRate;
WriteLog (lsDEBUG, OfferCreateTransactor) << boost::str (boost::format ("takeOffers: done: dir=%d uTakeQuality=%d %c uTipQuality=%d saTakerRate=%s %c saTipRate=%s bPassive=%d")
% !!sleOfferDir
% uTakeQuality
//.........这里部分代码省略.........
示例8: takeOffers
// Take as much as possible. Adjusts account balances. Charges fees on top to taker.
// --> uBookBase: The order book to take against.
// --> saTakerPays: What the taker offers (w/ issuer)
// --> saTakerGets: What the taker wanted (w/ issuer)
// <-- saTakerPaid: What taker could have paid including saved not including fees. To reduce an offer.
// <-- saTakerGot: What taker got not including fees. To reduce an offer.
// <-- terResult: tesSUCCESS, terNO_ACCOUNT, telFAILED_PROCESSING, or tecFAILED_PROCESSING
// <-- bUnfunded: if tesSUCCESS, consider offer unfunded after taking.
TER OfferCreateTransactor::takeOffers (
const bool bOpenLedger,
const bool bPassive,
const bool bSell,
uint256 const& uBookBase,
const uint160& uTakerAccountID,
SLE::ref sleTakerAccount,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
STAmount& saTakerPaid,
STAmount& saTakerGot,
bool& bUnfunded)
{
// The book has the most elements. Take the perspective of the book.
// Book is ordered for taker: taker pays / taker gets (smaller is better)
// The order is for the other books currencys for get and pays are opposites.
// We want the same ratio for the respective currencies.
// So we swap paid and gets for determing take quality.
assert (saTakerPays && saTakerGets);
WriteLog (lsDEBUG, OfferCreateTransactor) << "takeOffers: bSell: " << bSell << ": against book: " << uBookBase.ToString ();
LedgerEntrySet& lesActive = mEngine->getNodes ();
const uint64 uTakeQuality = STAmount::getRate (saTakerGets, saTakerPays);
STAmount saTakerRate = STAmount::setRate (uTakeQuality);
const uint160 uTakerPaysAccountID = saTakerPays.getIssuer ();
const uint160 uTakerGetsAccountID = saTakerGets.getIssuer ();
TER terResult = temUNCERTAIN;
boost::unordered_set<uint256> usOfferUnfundedBecame; // Offers that became unfunded.
boost::unordered_set<uint160> usAccountTouched; // Accounts touched.
saTakerPaid = STAmount (saTakerPays.getCurrency (), saTakerPays.getIssuer ());
saTakerGot = STAmount (saTakerGets.getCurrency (), saTakerGets.getIssuer ());
bUnfunded = false;
OrderBookIterator bookIterator (lesActive,
saTakerPays.getCurrency(), saTakerPays.getIssuer(),
saTakerGets.getCurrency(), saTakerGets.getIssuer());
while ((temUNCERTAIN == terResult) && bookIterator.nextOffer())
{
STAmount saTakerFunds = lesActive.accountFunds (uTakerAccountID, saTakerPays);
STAmount saSubTakerPays = saTakerPays - saTakerPaid; // How much more to spend.
STAmount saSubTakerGets = saTakerGets - saTakerGot; // How much more is wanted.
uint64 uTipQuality = bookIterator.getCurrentQuality();
if (!saTakerFunds.isPositive ())
{
// Taker is out of funds. Don't create the offer.
bUnfunded = true;
terResult = tesSUCCESS;
}
else if (!saSubTakerPays.isPositive() || !saSubTakerGets.isPositive())
{
// Offer is completely consumed
terResult = tesSUCCESS;
}
else if ((uTakeQuality < uTipQuality)
|| (bPassive && uTakeQuality == uTipQuality))
{
// Offer does not cross this offer
STAmount saTipRate = STAmount::setRate (uTipQuality);
WriteLog (lsDEBUG, OfferCreateTransactor) << boost::str (boost::format ("takeOffers: done: uTakeQuality=%d %c uTipQuality=%d saTakerRate=%s %c saTipRate=%s bPassive=%d")
% uTakeQuality
% (uTakeQuality == uTipQuality
? '='
: uTakeQuality < uTipQuality
? '<'
: '>')
% uTipQuality
% saTakerRate
% (saTakerRate == saTipRate
? '='
: saTakerRate < saTipRate
? '<'
: '>')
% saTipRate
% bPassive);
terResult = tesSUCCESS;
}
else
{
// We have a crossing offer to consider.
SLE::pointer sleOffer = bookIterator.getCurrentOffer ();
if (!sleOffer)
//.........这里部分代码省略.........
示例9: missing_field_error
static Json::Value signPayment(
Json::Value const& params,
Json::Value& tx_json,
RippleAddress const& raSrcAddressID,
Ledger::pointer lSnapshot,
int role)
{
RippleAddress dstAccountID;
if (!tx_json.isMember ("Amount"))
return RPC::missing_field_error ("tx_json.Amount");
STAmount amount;
if (!amount.bSetJson (tx_json ["Amount"]))
return RPC::invalid_field_error ("tx_json.Amount");
if (!tx_json.isMember ("Destination"))
return RPC::missing_field_error ("tx_json.Destination");
if (!dstAccountID.setAccountID (tx_json["Destination"].asString ()))
return RPC::invalid_field_error ("tx_json.Destination");
if (tx_json.isMember ("Paths") && params.isMember ("build_path"))
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot specify both 'tx_json.Paths' and 'tx_json.build_path'");
if (!tx_json.isMember ("Paths")
&& tx_json.isMember ("Amount")
&& params.isMember ("build_path"))
{
// Need a ripple path.
STPathSet spsPaths;
uint160 uSrcCurrencyID;
uint160 uSrcIssuerID;
STAmount saSendMax;
if (tx_json.isMember ("SendMax"))
{
if (!saSendMax.bSetJson (tx_json ["SendMax"]))
return RPC::invalid_field_error ("tx_json.SendMax");
}
else
{
// If no SendMax, default to Amount with sender as issuer.
saSendMax = amount;
saSendMax.setIssuer (raSrcAddressID.getAccountID ());
}
if (saSendMax.isNative () && amount.isNative ())
return RPC::make_error (rpcINVALID_PARAMS,
"Cannot build STR to STR paths.");
{
LegacyPathFind lpf (role == Config::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
bool bValid;
auto cache = boost::make_shared<RippleLineCache> (lSnapshot);
Pathfinder pf (cache, raSrcAddressID, dstAccountID,
saSendMax.getCurrency (), saSendMax.getIssuer (),
amount, bValid);
STPath extraPath;
if (!bValid || !pf.findPaths (getConfig ().PATH_SEARCH_OLD, 4, spsPaths, extraPath))
{
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: No paths found.";
return rpcError (rpcNO_PATH);
}
WriteLog (lsDEBUG, RPCHandler)
<< "transactionSign: build_path: "
<< spsPaths.getJson (0);
if (!spsPaths.isEmpty ())
tx_json["Paths"] = spsPaths.getJson (0);
}
}
return Json::Value();
}
示例10: doApply
TER SetTrust::doApply ()
{
TER terResult = tesSUCCESS;
STAmount const saLimitAmount (mTxn.getFieldAmount (sfLimitAmount));
bool const bQualityIn (mTxn.isFieldPresent (sfQualityIn));
bool const bQualityOut (mTxn.isFieldPresent (sfQualityOut));
Currency const currency (saLimitAmount.getCurrency ());
Account uDstAccountID (saLimitAmount.getIssuer ());
// true, iff current is high account.
bool const bHigh = mTxnAccountID > uDstAccountID;
std::uint32_t uQualityIn (bQualityIn ? mTxn.getFieldU32 (sfQualityIn) : 0);
std::uint32_t uQualityOut (bQualityOut ? mTxn.getFieldU32 (sfQualityOut) : 0);
if (!saLimitAmount.isLegalNet ())
return temBAD_AMOUNT;
if (bQualityIn && QUALITY_ONE == uQualityIn)
uQualityIn = 0;
if (bQualityOut && QUALITY_ONE == uQualityOut)
uQualityOut = 0;
std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfTrustSetMask)
{
m_journal.trace <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
bool const bSetAuth = (uTxFlags & tfSetfAuth);
bool const bSetNoRipple = (uTxFlags & tfSetNoRipple);
bool const bClearNoRipple = (uTxFlags & tfClearNoRipple);
bool const bSetFreeze = (uTxFlags & tfSetFreeze);
bool const bClearFreeze = (uTxFlags & tfClearFreeze);
if (bSetAuth && !(mTxnAccount->getFieldU32 (sfFlags) & lsfRequireAuth))
{
m_journal.trace <<
"Retry: Auth not required.";
return tefNO_AUTH_REQUIRED;
}
if (saLimitAmount.isNative ())
{
m_journal.trace <<
"Malformed transaction: Native credit limit: " <<
saLimitAmount.getFullText ();
return temBAD_LIMIT;
}
if (saLimitAmount < zero)
{
m_journal.trace <<
"Malformed transaction: Negative credit limit.";
return temBAD_LIMIT;
}
// Check if destination makes sense.
if (!uDstAccountID || uDstAccountID == noAccount())
{
m_journal.trace <<
"Malformed transaction: Destination account not specified.";
return temDST_NEEDED;
}
if (mTxnAccountID == uDstAccountID)
{
SLE::pointer selDelete (
mEngine->entryCache (ltRIPPLE_STATE,
Ledger::getRippleStateIndex (
mTxnAccountID, uDstAccountID, currency)));
if (selDelete)
{
m_journal.warning <<
"Clearing redundant line.";
return mEngine->view ().trustDelete (
selDelete, mTxnAccountID, uDstAccountID);
}
else
{
m_journal.trace <<
"Malformed transaction: Can not extend credit to self.";
return temDST_IS_SRC;
}
}
SLE::pointer sleDst (mEngine->entryCache (
ltACCOUNT_ROOT, Ledger::getAccountRootIndex (uDstAccountID)));
if (!sleDst)
{
//.........这里部分代码省略.........
示例11: doApply
TER PaymentTransactor::doApply ()
{
// Ripple if source or destination is non-native or if there are paths.
std::uint32_t const uTxFlags = mTxn.getFlags ();
//bool const bPartialPayment = is_bit_set(uTxFlags, tfPartialPayment);
bool const bLimitQuality = is_bit_set (uTxFlags, tfLimitQuality);
bool const bNoRippleDirect = is_bit_set (uTxFlags, tfNoRippleDirect);
bool const bPaths = mTxn.isFieldPresent (sfPaths);
bool const bMax = mTxn.isFieldPresent (sfSendMax);
uint160 const uDstAccountID = mTxn.getFieldAccount160 (sfDestination);
STAmount const saDstAmount = mTxn.getFieldAmount (sfAmount);
STAmount const saMaxAmount = bMax
? mTxn.getFieldAmount (sfSendMax)
: saDstAmount.isNative ()
? saDstAmount
: STAmount (saDstAmount.getCurrency (),
mTxnAccountID,
saDstAmount.getMantissa (),
saDstAmount.getExponent (),
saDstAmount < zero);
uint160 const uSrcCurrency = saMaxAmount.getCurrency ();
uint160 const uDstCurrency = saDstAmount.getCurrency ();
bool const bSTRDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
m_journal.trace <<
"saMaxAmount=" << saMaxAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText ();
if (!saDstAmount.isLegalNet () || !saMaxAmount.isLegalNet ())
return temBAD_AMOUNT;
if (uTxFlags & tfPaymentMask)
{
m_journal.trace <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
else if (!uDstAccountID)
{
m_journal.trace <<
"Malformed transaction: Payment destination account not specified.";
return temDST_NEEDED;
}
else if (bMax && saMaxAmount <= zero)
{
m_journal.trace <<
"Malformed transaction: bad max amount: " << saMaxAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (saDstAmount <= zero)
{
m_journal.trace <<
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (CURRENCY_BAD == uSrcCurrency || CURRENCY_BAD == uDstCurrency)
{
m_journal.trace <<
"Malformed transaction: Bad currency.";
return temBAD_CURRENCY;
}
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{
m_journal.trace <<
"Malformed transaction: Redundant transaction:" <<
" src=" << to_string (mTxnAccountID) <<
" dst=" << to_string (uDstAccountID) <<
" src_cur=" << to_string (uSrcCurrency) <<
" dst_cur=" << to_string (uDstCurrency);
return temREDUNDANT;
}
else if (bMax && saMaxAmount == saDstAmount && saMaxAmount.getCurrency () == saDstAmount.getCurrency ())
{
m_journal.trace <<
"Malformed transaction: Redundant SendMax.";
return temREDUNDANT_SEND_MAX;
}
else if (bSTRDirect && bMax)
{
m_journal.trace <<
"Malformed transaction: SendMax specified for STR to STR.";
return temBAD_SEND_STR_MAX;
}
else if (bSTRDirect && bPaths)
{
m_journal.trace <<
"Malformed transaction: Paths specified for STR to STR.";
return temBAD_SEND_STR_PATHS;
}
else if (bSTRDirect && bLimitQuality)
//.........这里部分代码省略.........
示例12: doRipplePathFind
// This interface is deprecated.
Json::Value doRipplePathFind (RPC::Context& context)
{
RPC::LegacyPathFind lpf (context.role == Role::ADMIN);
if (!lpf.isOk ())
return rpcError (rpcTOO_BUSY);
context.loadType = Resource::feeHighBurdenRPC;
RippleAddress raSrc;
RippleAddress raDst;
STAmount saDstAmount;
Ledger::pointer lpLedger;
Json::Value jvResult;
if (getConfig().RUN_STANDALONE ||
context.params.isMember(jss::ledger) ||
context.params.isMember(jss::ledger_index) ||
context.params.isMember(jss::ledger_hash))
{
// The caller specified a ledger
jvResult = RPC::lookupLedger (
context.params, lpLedger, context.netOps);
if (!lpLedger)
return jvResult;
}
if (!context.params.isMember (jss::source_account))
{
jvResult = rpcError (rpcSRC_ACT_MISSING);
}
else if (!context.params[jss::source_account].isString ()
|| !raSrc.setAccountID (
context.params[jss::source_account].asString ()))
{
jvResult = rpcError (rpcSRC_ACT_MALFORMED);
}
else if (!context.params.isMember (jss::destination_account))
{
jvResult = rpcError (rpcDST_ACT_MISSING);
}
else if (!context.params[jss::destination_account].isString ()
|| !raDst.setAccountID (
context.params[jss::destination_account].asString ()))
{
jvResult = rpcError (rpcDST_ACT_MALFORMED);
}
else if (
// Parse saDstAmount.
!context.params.isMember (jss::destination_amount)
|| ! amountFromJsonNoThrow(saDstAmount, context.params[jss::destination_amount])
|| saDstAmount <= zero
|| (!isXRP(saDstAmount.getCurrency ())
&& (!saDstAmount.getIssuer () ||
noAccount() == saDstAmount.getIssuer ())))
{
WriteLog (lsINFO, RPCHandler) << "Bad destination_amount.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else if (
// Checks on source_currencies.
context.params.isMember (jss::source_currencies)
&& (!context.params[jss::source_currencies].isArray ()
|| !context.params[jss::source_currencies].size ())
// Don't allow empty currencies.
)
{
WriteLog (lsINFO, RPCHandler) << "Bad source_currencies.";
jvResult = rpcError (rpcINVALID_PARAMS);
}
else
{
context.loadType = Resource::feeHighBurdenRPC;
RippleLineCache::pointer cache;
if (lpLedger)
{
// The caller specified a ledger
lpLedger = std::make_shared<Ledger> (std::ref (*lpLedger), false);
cache = std::make_shared<RippleLineCache>(lpLedger);
}
else
{
// The closed ledger is recent and any nodes made resident
// have the best chance to persist
lpLedger = context.netOps.getClosedLedger();
cache = getApp().getPathRequests().getLineCache(lpLedger, false);
}
Json::Value jvSrcCurrencies;
if (context.params.isMember (jss::source_currencies))
{
jvSrcCurrencies = context.params[jss::source_currencies];
}
else
{
jvSrcCurrencies = buildSrcCurrencies(raSrc, cache);
}
//.........这里部分代码省略.........
示例13: preCheck
TER preCheck () override
{
std::uint32_t const uTxFlags = mTxn.getFlags ();
if (uTxFlags & tfPaymentMask)
{
m_journal.trace << "Malformed transaction: " <<
"Invalid flags set.";
return temINVALID_FLAG;
}
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
bool const limitQuality = uTxFlags & tfLimitQuality;
bool const defaultPathsAllowed = !(uTxFlags & tfNoDivvyDirect);
bool const bPaths = mTxn.isFieldPresent (sfPaths);
bool const bMax = mTxn.isFieldPresent (sfSendMax);
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
STAmount maxSourceAmount;
if (bMax)
maxSourceAmount = mTxn.getFieldAmount (sfSendMax);
else if (saDstAmount.native ())
maxSourceAmount = saDstAmount;
else
maxSourceAmount = STAmount (
{ saDstAmount.getCurrency (), mTxnAccountID },
saDstAmount.mantissa(), saDstAmount.exponent (),
saDstAmount < zero);
auto const& uSrcCurrency = maxSourceAmount.getCurrency ();
auto const& uDstCurrency = saDstAmount.getCurrency ();
// isZero() is XDV. FIX!
bool const bXDVDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
if (!isLegalNet (saDstAmount) || !isLegalNet (maxSourceAmount))
return temBAD_AMOUNT;
AccountID const uDstAccountID (mTxn.getFieldAccount160 (sfDestination));
if (!uDstAccountID)
{
m_journal.trace << "Malformed transaction: " <<
"Payment destination account not specified.";
return temDST_NEEDED;
}
if (bMax && maxSourceAmount <= zero)
{
m_journal.trace << "Malformed transaction: " <<
"bad max amount: " << maxSourceAmount.getFullText ();
return temBAD_AMOUNT;
}
if (saDstAmount <= zero)
{
m_journal.trace << "Malformed transaction: "<<
"bad dst amount: " << saDstAmount.getFullText ();
return temBAD_AMOUNT;
}
if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
{
m_journal.trace <<"Malformed transaction: " <<
"Bad currency.";
return temBAD_CURRENCY;
}
if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{
// You're signing yourself a payment.
// If bPaths is true, you might be trying some arbitrage.
m_journal.trace << "Malformed transaction: " <<
"Redundant payment from " << to_string (mTxnAccountID) <<
" to self without path for " << to_string (uDstCurrency);
return temREDUNDANT;
}
if (bXDVDirect && bMax)
{
// Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " <<
"SendMax specified for XDV to XDV.";
return temBAD_SEND_XDV_MAX;
}
if (bXDVDirect && bPaths)
{
// XDV is sent without paths.
m_journal.trace << "Malformed transaction: " <<
"Paths specified for XDV to XDV.";
return temBAD_SEND_XDV_PATHS;
}
if (bXDVDirect && partialPaymentAllowed)
{
// Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " <<
"Partial payment specified for XDV to XDV.";
return temBAD_SEND_XDV_PARTIAL;
}
if (bXDVDirect && limitQuality)
{
// Consistent but redundant transaction.
m_journal.trace << "Malformed transaction: " <<
//.........这里部分代码省略.........
示例14: doApply
TER doApply () override
{
// Ripple if source or destination is non-native or if there are paths.
std::uint32_t const uTxFlags = mTxn.getFlags ();
bool const partialPaymentAllowed = uTxFlags & tfPartialPayment;
bool const limitQuality = uTxFlags & tfLimitQuality;
bool const defaultPathsAllowed = !(uTxFlags & tfNoRippleDirect);
bool const bPaths = mTxn.isFieldPresent (sfPaths);
bool const bMax = mTxn.isFieldPresent (sfSendMax);
Account const uDstAccountID (mTxn.getFieldAccount160 (sfDestination));
STAmount const saDstAmount (mTxn.getFieldAmount (sfAmount));
STAmount maxSourceAmount;
if (bMax)
maxSourceAmount = mTxn.getFieldAmount (sfSendMax);
else if (saDstAmount.isNative ())
maxSourceAmount = saDstAmount;
else
maxSourceAmount = STAmount (
{saDstAmount.getCurrency (), mTxnAccountID},
saDstAmount.mantissa(), saDstAmount.exponent (),
saDstAmount < zero);
auto const& uSrcCurrency = maxSourceAmount.getCurrency ();
auto const& uDstCurrency = saDstAmount.getCurrency ();
// isZero() is XRP. FIX!
bool const bXRPDirect = uSrcCurrency.isZero () && uDstCurrency.isZero ();
m_journal.trace <<
"maxSourceAmount=" << maxSourceAmount.getFullText () <<
" saDstAmount=" << saDstAmount.getFullText ();
if (!isLegalNet (saDstAmount) || !isLegalNet (maxSourceAmount))
return temBAD_AMOUNT;
if (uTxFlags & tfPaymentMask)
{
m_journal.trace <<
"Malformed transaction: Invalid flags set.";
return temINVALID_FLAG;
}
else if (!uDstAccountID)
{
m_journal.trace <<
"Malformed transaction: Payment destination account not specified.";
return temDST_NEEDED;
}
else if (bMax && maxSourceAmount <= zero)
{
m_journal.trace <<
"Malformed transaction: bad max amount: " << maxSourceAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (saDstAmount <= zero)
{
m_journal.trace <<
"Malformed transaction: bad dst amount: " << saDstAmount.getFullText ();
return temBAD_AMOUNT;
}
else if (badCurrency() == uSrcCurrency || badCurrency() == uDstCurrency)
{
m_journal.trace <<
"Malformed transaction: Bad currency.";
return temBAD_CURRENCY;
}
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{
// You're signing yourself a payment.
// If bPaths is true, you might be trying some arbitrage.
m_journal.trace <<
"Malformed transaction: Redundant transaction:" <<
" src=" << to_string (mTxnAccountID) <<
" dst=" << to_string (uDstAccountID) <<
" src_cur=" << to_string (uSrcCurrency) <<
" dst_cur=" << to_string (uDstCurrency);
return temREDUNDANT;
}
else if (bMax && maxSourceAmount == saDstAmount &&
maxSourceAmount.getCurrency () == saDstAmount.getCurrency ())
{
// Consistent but redundant transaction.
m_journal.trace <<
"Malformed transaction: Redundant SendMax.";
return temREDUNDANT_SEND_MAX;
}
else if (bXRPDirect && bMax)
{
// Consistent but redundant transaction.
m_journal.trace <<
"Malformed transaction: SendMax specified for XRP to XRP.";
return temBAD_SEND_XRP_MAX;
}
else if (bXRPDirect && bPaths)
//.........这里部分代码省略.........
示例15: rippleLiquidity
void rippleLiquidity (
RippleCalc& rippleCalc,
Rate const& qualityIn,
Rate const& qualityOut,
STAmount const& saPrvReq, // --> in limit including fees, <0 = unlimited
STAmount const& saCurReq, // --> out limit
STAmount& saPrvAct, // <-> in limit including achieved so far: <-- <= -->
STAmount& saCurAct, // <-> out limit including achieved so far: <-- <= -->
std::uint64_t& uRateMax)
{
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity>"
<< " qualityIn=" << qualityIn
<< " qualityOut=" << qualityOut
<< " saPrvReq=" << saPrvReq
<< " saCurReq=" << saCurReq
<< " saPrvAct=" << saPrvAct
<< " saCurAct=" << saCurAct;
// saCurAct was once zero in a production server.
assert (saCurReq != zero);
assert (saCurReq > zero);
assert (saPrvReq.getCurrency () == saCurReq.getCurrency ());
assert (saPrvReq.getCurrency () == saPrvAct.getCurrency ());
assert (saPrvReq.getIssuer () == saPrvAct.getIssuer ());
const bool bPrvUnlimited = (saPrvReq < zero); // -1 means unlimited.
// Unlimited stays unlimited - don't do calculations.
// How much could possibly flow through the previous node?
const STAmount saPrv = bPrvUnlimited ? saPrvReq : saPrvReq - saPrvAct;
// How much could possibly flow through the current node?
const STAmount saCur = saCurReq - saCurAct;
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity: "
<< " bPrvUnlimited=" << bPrvUnlimited
<< " saPrv=" << saPrv
<< " saCur=" << saCur;
// If nothing can flow, we might as well not do any work.
if (saPrv == zero || saCur == zero)
return;
if (qualityIn >= qualityOut)
{
// You're getting better quality than you asked for, so no fee.
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: No fees";
// Only process if the current rate, 1:1, is not worse than the previous
// rate, uRateMax - otherwise there is no flow.
if (!uRateMax || STAmount::uRateOne <= uRateMax)
{
// Limit amount to transfer if need - the minimum of amount being
// paid and the amount that's wanted.
STAmount saTransfer = bPrvUnlimited ? saCur
: std::min (saPrv, saCur);
// In reverse, we want to propagate the limited cur to prv and set
// actual cur.
//
// In forward, we want to propagate the limited prv to cur and set
// actual prv.
//
// This is the actual flow.
saPrvAct += saTransfer;
saCurAct += saTransfer;
// If no rate limit, set rate limit to avoid combining with
// something with a worse rate.
if (uRateMax == 0)
uRateMax = STAmount::uRateOne;
}
}
else
{
// If the quality is worse than the previous
JLOG (rippleCalc.j_.trace()) << "rippleLiquidity: Fee";
std::uint64_t const uRate = getRate (
STAmount (qualityOut.value),
STAmount (qualityIn.value));
// If the next rate is at least as good as the current rate, process.
if (!uRateMax || uRate <= uRateMax)
{
// current actual = current request * (quality out / quality in).
auto numerator = multiplyRound (saCur, qualityOut, true);
// True means "round up" to get best flow.
STAmount saCurIn = divideRound (numerator, qualityIn, true);
JLOG (rippleCalc.j_.trace())
<< "rippleLiquidity:"
<< " bPrvUnlimited=" << bPrvUnlimited
<< " saPrv=" << saPrv
<< " saCurIn=" << saCurIn;
//.........这里部分代码省略.........