mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
171 lines
5.2 KiB
C++
171 lines
5.2 KiB
C++
#include "TrustSetTransactor.h"
|
|
|
|
#include <boost/bind.hpp>
|
|
|
|
TER TrustSetTransactor::doApply()
|
|
{
|
|
TER terResult = tesSUCCESS;
|
|
Log(lsINFO) << "doTrustSet>";
|
|
|
|
const STAmount saLimitAmount = mTxn.getFieldAmount(sfLimitAmount);
|
|
const bool bQualityIn = mTxn.isFieldPresent(sfQualityIn);
|
|
const uint32 uQualityIn = bQualityIn ? mTxn.getFieldU32(sfQualityIn) : 0;
|
|
const bool bQualityOut = mTxn.isFieldPresent(sfQualityOut);
|
|
const uint32 uQualityOut = bQualityIn ? mTxn.getFieldU32(sfQualityOut) : 0;
|
|
const uint160 uCurrencyID = saLimitAmount.getCurrency();
|
|
uint160 uDstAccountID = saLimitAmount.getIssuer();
|
|
const bool bFlipped = mTxnAccountID > uDstAccountID; // true, iff current is not lowest.
|
|
bool bDelIndex = false;
|
|
|
|
// Check if destination makes sense.
|
|
|
|
if (saLimitAmount.isNegative())
|
|
{
|
|
Log(lsINFO) << "doTrustSet: Malformed transaction: Negatived credit limit.";
|
|
|
|
return temBAD_AMOUNT;
|
|
}
|
|
else if (!uDstAccountID || uDstAccountID == ACCOUNT_ONE)
|
|
{
|
|
Log(lsINFO) << "doTrustSet: Malformed transaction: Destination account not specified.";
|
|
|
|
return temDST_NEEDED;
|
|
}
|
|
else if (mTxnAccountID == uDstAccountID)
|
|
{
|
|
Log(lsINFO) << "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)
|
|
{
|
|
Log(lsINFO) << "doTrustSet: Delay transaction: Destination account does not exist.";
|
|
|
|
return terNO_DST;
|
|
}
|
|
|
|
STAmount saLimitAllow = saLimitAmount;
|
|
saLimitAllow.setIssuer(mTxnAccountID);
|
|
|
|
SLE::pointer sleRippleState = mEngine->entryCache(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID));
|
|
if (sleRippleState)
|
|
{
|
|
// A line exists in one or more directions.
|
|
|
|
#if 0
|
|
// We might delete a ripple state node if everything is set to defaults.
|
|
// However, this is problematic as it may make predicting reserve amounts harder for users.
|
|
// The code here is incomplete.
|
|
|
|
if (!saLimitAmount)
|
|
{
|
|
// Zeroing line.
|
|
uint160 uLowID = sleRippleState->getFieldAmount(sfLowLimit).getIssuer();
|
|
uint160 uHighID = sleRippleState->getFieldAmount(sfHighLimit).getIssuer();
|
|
bool bLow = uLowID == uSrcAccountID;
|
|
bool bHigh = uLowID == uDstAccountID;
|
|
bool bBalanceZero = !sleRippleState->getFieldAmount(sfBalance);
|
|
STAmount saDstLimit = sleRippleState->getFieldAmount(bSendLow ? sfLowLimit : sfHighLimit);
|
|
bool bDstLimitZero = !saDstLimit;
|
|
|
|
assert(bLow || bHigh);
|
|
|
|
if (bBalanceZero && bDstLimitZero)
|
|
{
|
|
// Zero balance and eliminating last limit.
|
|
|
|
bDelIndex = true;
|
|
terResult = dirDelete(false, uSrcRef, Ledger::getOwnerDirIndex(mTxnAccountID), sleRippleState->getIndex(), false);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!bDelIndex)
|
|
{
|
|
sleRippleState->setFieldAmount(bFlipped ? sfHighLimit: sfLowLimit, saLimitAllow);
|
|
|
|
if (!bQualityIn)
|
|
{
|
|
nothing();
|
|
}
|
|
else if (uQualityIn)
|
|
{
|
|
sleRippleState->setFieldU32(bFlipped ? sfLowQualityIn : sfHighQualityIn, uQualityIn);
|
|
}
|
|
else
|
|
{
|
|
sleRippleState->makeFieldAbsent(bFlipped ? sfLowQualityIn : sfHighQualityIn);
|
|
}
|
|
|
|
if (!bQualityOut)
|
|
{
|
|
nothing();
|
|
}
|
|
else if (uQualityOut)
|
|
{
|
|
sleRippleState->setFieldU32(bFlipped ? sfLowQualityOut : sfHighQualityOut, uQualityOut);
|
|
}
|
|
else
|
|
{
|
|
sleRippleState->makeFieldAbsent(bFlipped ? sfLowQualityOut : sfHighQualityOut);
|
|
}
|
|
|
|
mEngine->entryModify(sleRippleState);
|
|
}
|
|
|
|
Log(lsINFO) << "doTrustSet: Modifying ripple line: bDelIndex=" << bDelIndex;
|
|
}
|
|
// Line does not exist.
|
|
else if (!saLimitAmount)
|
|
{
|
|
Log(lsINFO) << "doTrustSet: Redundant: Setting non-existent ripple line to 0.";
|
|
|
|
return terNO_LINE_NO_ZERO;
|
|
}
|
|
else
|
|
{
|
|
// Create a new ripple line.
|
|
sleRippleState = mEngine->entryCreate(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID));
|
|
|
|
Log(lsINFO) << "doTrustSet: Creating ripple line: " << sleRippleState->getIndex().ToString();
|
|
|
|
sleRippleState->setFieldAmount(sfBalance, STAmount(uCurrencyID, ACCOUNT_ONE)); // Zero balance in currency.
|
|
sleRippleState->setFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, saLimitAllow);
|
|
sleRippleState->setFieldAmount(bFlipped ? sfLowLimit : sfHighLimit, STAmount(uCurrencyID, uDstAccountID));
|
|
|
|
if (uQualityIn)
|
|
sleRippleState->setFieldU32(bFlipped ? sfHighQualityIn : sfLowQualityIn, uQualityIn);
|
|
if (uQualityOut)
|
|
sleRippleState->setFieldU32(bFlipped ? sfHighQualityOut : sfLowQualityOut, uQualityOut);
|
|
|
|
uint64 uSrcRef; // <-- Ignored, dirs never delete.
|
|
|
|
terResult = mEngine->getNodes().dirAdd(
|
|
uSrcRef,
|
|
Ledger::getOwnerDirIndex(mTxnAccountID),
|
|
sleRippleState->getIndex(),
|
|
boost::bind(&Ledger::ownerDirDescriber, _1, mTxnAccountID));
|
|
|
|
if (tesSUCCESS == terResult)
|
|
terResult = mEngine->getNodes().ownerCountAdjust(mTxnAccountID, 1, mTxnAccount);
|
|
|
|
if (tesSUCCESS == terResult)
|
|
terResult = mEngine->getNodes().dirAdd(
|
|
uSrcRef,
|
|
Ledger::getOwnerDirIndex(uDstAccountID),
|
|
sleRippleState->getIndex(),
|
|
boost::bind(&Ledger::ownerDirDescriber, _1, uDstAccountID));
|
|
|
|
if (tesSUCCESS == terResult)
|
|
terResult = mEngine->getNodes().ownerCountAdjust(uDstAccountID, 1, sleDst);
|
|
}
|
|
|
|
Log(lsINFO) << "doTrustSet<";
|
|
|
|
return terResult;
|
|
}
|
|
|
|
// vim:ts=4
|