mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-02 00:45:58 +00:00
New fee stuff.
CAUTION: Code is currently in an untested state.
This commit is contained in:
@@ -40,7 +40,7 @@ DatabaseCon::~DatabaseCon()
|
||||
Application::Application() :
|
||||
mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mLedgerMaster),
|
||||
mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300),
|
||||
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(theConfig.TRANSACTION_FEE_BASE, theConfig.FEE_DEFAULT),
|
||||
mSNTPClient(mAuxService), mRPCHandler(&mNetOps), mFeeTrack(),
|
||||
mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mWSPublicDoor(NULL), mWSPrivateDoor(NULL),
|
||||
mSweepTimer(mAuxService)
|
||||
|
||||
@@ -112,6 +112,7 @@ public:
|
||||
boost::recursive_mutex& getMasterLock() { return mMasterLock; }
|
||||
ProofOfWorkGenerator& getPowGen() { return mPOWGen; }
|
||||
LoadManager& getLoadManager() { return mLoadMgr; }
|
||||
LoadFeeTrack& getFeeTrack() { return mFeeTrack; }
|
||||
TXQueue& getTxnQueue() { return mTxnQueue; }
|
||||
|
||||
|
||||
@@ -121,8 +122,6 @@ public:
|
||||
bool isNewFlag(const uint256& s, int f) { return mSuppressions.setFlag(s, f); }
|
||||
bool running() { return mTxnDB != NULL; }
|
||||
bool getSystemTimeOffset(int& offset) { return mSNTPClient.getOffset(offset); }
|
||||
uint64 scaleFeeBase(uint64 fee) { return mFeeTrack.scaleFeeBase(fee); }
|
||||
uint64 scaleFeeLoad(uint64 fee) { return mFeeTrack.scaleFeeLoad(fee); }
|
||||
|
||||
DatabaseCon* getRpcDB() { return mRpcDB; }
|
||||
DatabaseCon* getTxnDB() { return mTxnDB; }
|
||||
|
||||
@@ -37,6 +37,7 @@ Ledger::Ledger(const RippleAddress& masterID, uint64 startAmount) : mTotCoins(st
|
||||
mAccountStateMap->armDirty();
|
||||
writeBack(lepCREATE, startAccount->getSLE());
|
||||
SHAMap::flushDirty(*mAccountStateMap->disarmDirty(), 256, hotACCOUNT_NODE, mLedgerSeq);
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||
@@ -55,6 +56,7 @@ Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint25
|
||||
mAccountStateMap->fetchRoot(mAccountHash);
|
||||
mTransactionMap->setImmutable();
|
||||
mAccountStateMap->setImmutable();
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mLedgerSeq(ledger.mLedgerSeq),
|
||||
@@ -65,6 +67,7 @@ Ledger::Ledger(Ledger& ledger, bool isMutable) : mTotCoins(ledger.mTotCoins), mL
|
||||
mAccountStateMap(ledger.mAccountStateMap->snapShot(isMutable))
|
||||
{ // Create a new ledger that's a snapshot of this one
|
||||
updateHash();
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +91,7 @@ Ledger::Ledger(bool /* dummy */, Ledger& prevLedger) :
|
||||
}
|
||||
else
|
||||
mCloseTime = prevLedger.mCloseTime + mCloseResolution;
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) :
|
||||
@@ -95,6 +99,7 @@ Ledger::Ledger(const std::vector<unsigned char>& rawLedger) :
|
||||
{
|
||||
Serializer s(rawLedger);
|
||||
setRaw(s);
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
Ledger::Ledger(const std::string& rawLedger) :
|
||||
@@ -102,6 +107,7 @@ Ledger::Ledger(const std::string& rawLedger) :
|
||||
{
|
||||
Serializer s(rawLedger);
|
||||
setRaw(s);
|
||||
zeroFees();
|
||||
}
|
||||
|
||||
void Ledger::updateHash()
|
||||
@@ -899,6 +905,13 @@ uint256 Ledger::getAccountRootIndex(const uint160& uAccountID)
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getLedgerFeeIndex()
|
||||
{ // get the index of the node that holds the fee schedul
|
||||
Serializer s(2);
|
||||
s.add16(spaceFee);
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint256 Ledger::getLedgerFeatureIndex()
|
||||
{ // get the index of the node that holds the last 256 ledgers
|
||||
Serializer s(2);
|
||||
@@ -1185,5 +1198,51 @@ void Ledger::qualityDirDescriber(SLE::ref sle,
|
||||
sle->setFieldU64(sfExchangeRate, uRate);
|
||||
}
|
||||
|
||||
void Ledger::zeroFees()
|
||||
{
|
||||
mBaseFee = 0;
|
||||
mReferenceFeeUnits = 0;
|
||||
mReserveBase = 0;
|
||||
mReserveIncrement = 0;
|
||||
}
|
||||
|
||||
void Ledger::updateFees()
|
||||
{
|
||||
mBaseFee = theConfig.FEE_DEFAULT;
|
||||
mReferenceFeeUnits = 10;
|
||||
mReserveBase = theConfig.FEE_ACCOUNT_RESERVE;
|
||||
mReserveIncrement = theConfig.FEE_OWNER_RESERVE;
|
||||
|
||||
LedgerStateParms p = lepNONE;
|
||||
SLE::pointer sle = getASNode(p, Ledger::getLedgerFeeIndex(), ltFEE_SETTINGS);
|
||||
if (!sle)
|
||||
return;
|
||||
|
||||
if (sle->getFieldIndex(sfBaseFee) != -1)
|
||||
mBaseFee = sle->getFieldU64(sfBaseFee);
|
||||
|
||||
if (sle->getFieldIndex(sfReferenceFeeUnits) != -1)
|
||||
mReferenceFeeUnits = sle->getFieldU32(sfReferenceFeeUnits);
|
||||
|
||||
if (sle->getFieldIndex(sfReserveBase) != -1)
|
||||
mReserveBase = sle->getFieldU32(sfReserveBase);
|
||||
|
||||
if (sle->getFieldIndex(sfReserveIncrement) != -1)
|
||||
mReserveIncrement = sle->getFieldU32(sfReserveIncrement);
|
||||
}
|
||||
|
||||
uint64 Ledger::scaleFeeBase(uint64 fee)
|
||||
{
|
||||
if (!mBaseFee)
|
||||
updateFees();
|
||||
return theApp->getFeeTrack().scaleFeeBase(fee, mBaseFee, mReferenceFeeUnits);
|
||||
}
|
||||
|
||||
uint64 Ledger::scaleFeeLoad(uint64 fee)
|
||||
{
|
||||
if (!mBaseFee)
|
||||
updateFees();
|
||||
return theApp->getFeeTrack().scaleFeeLoad(fee, mBaseFee, mReferenceFeeUnits);
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -78,6 +78,10 @@ private:
|
||||
uint32 mCloseFlags; // flags indicating how this ledger close took place
|
||||
bool mClosed, mValidHash, mAccepted, mImmutable;
|
||||
|
||||
uint32 mReferenceFeeUnits; // Fee units for the reference transaction
|
||||
uint32 mReserveBase, mReserveIncrement; // Reserve basse and increment in fee units
|
||||
uint64 mBaseFee; // Ripple cost of the reference transaction
|
||||
|
||||
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
||||
|
||||
mutable boost::recursive_mutex mLock;
|
||||
@@ -95,6 +99,9 @@ protected:
|
||||
static void decPendingSaves();
|
||||
void saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer);
|
||||
|
||||
void updateFees();
|
||||
void zeroFees();
|
||||
|
||||
public:
|
||||
Ledger(const RippleAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
||||
|
||||
@@ -193,6 +200,7 @@ public:
|
||||
static int getLedgerHashOffset(uint32 desiredLedgerIndex, uint32 currentLedgerIndex);
|
||||
|
||||
static uint256 getLedgerFeatureIndex();
|
||||
static uint256 getLedgerFeeIndex();
|
||||
|
||||
// index calculation functions
|
||||
static uint256 getAccountRootIndex(const uint160& uAccountID);
|
||||
@@ -304,6 +312,28 @@ public:
|
||||
SLE::pointer getRippleState(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
||||
{ return getRippleState(getRippleStateIndex(RippleAddress::createAccountID(uiA), RippleAddress::createAccountID(uiB), uCurrency)); }
|
||||
|
||||
uint32 getReferenceFeeUnits()
|
||||
{
|
||||
if (!mBaseFee) updateFees();
|
||||
return mReferenceFeeUnits;
|
||||
}
|
||||
|
||||
uint64 getBaseFee()
|
||||
{
|
||||
if (!mBaseFee) updateFees();
|
||||
return mBaseFee;
|
||||
}
|
||||
|
||||
uint64 getReserve(int increments)
|
||||
{
|
||||
if (!mBaseFee) updateFees();
|
||||
return scaleFeeBase(static_cast<uint64>(increments) * mReserveIncrement + mReserveBase);
|
||||
}
|
||||
|
||||
uint64 scaleFeeBase(uint64 fee);
|
||||
uint64 scaleFeeLoad(uint64 fee);
|
||||
|
||||
|
||||
Json::Value getJson(int options);
|
||||
void addJson(Json::Value&, int options);
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ bool LoadManager::adjust(LoadSource& source, int credits) const
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint32 div)
|
||||
uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint64 div)
|
||||
{ // compute (value)*(mul)/(div) - avoid overflow but keep precision
|
||||
static uint64 boundary = (0x00000000FFFFFFFF);
|
||||
if (value > boundary) // Large value, avoid overflow
|
||||
@@ -147,45 +147,32 @@ uint64 LoadFeeTrack::mulDiv(uint64 value, uint32 mul, uint32 div)
|
||||
return (value * mul) / div;
|
||||
}
|
||||
|
||||
uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee)
|
||||
uint64 LoadFeeTrack::scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
static uint64 midrange(0x00000000FFFFFFFF);
|
||||
|
||||
bool big = (fee > midrange);
|
||||
if (big) // big fee, divide first to avoid overflow
|
||||
fee /= baseFee;
|
||||
else // normal fee, multiply first for accuracy
|
||||
fee *= referenceFeeUnits;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
if (big) // big fee, divide first to avoid overflow
|
||||
fee /= mBaseFee;
|
||||
else // normal fee, multiply first for accuracy
|
||||
fee *= mBaseRef;
|
||||
|
||||
fee = mulDiv(fee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee);
|
||||
|
||||
if (big) // Fee was big to start, must now multiply
|
||||
fee *= mBaseRef;
|
||||
else // Fee was small to start, mst now divide
|
||||
fee /= mBaseFee;
|
||||
}
|
||||
|
||||
if (big) // Fee was big to start, must now multiply
|
||||
fee *= referenceFeeUnits;
|
||||
else // Fee was small to start, mst now divide
|
||||
fee /= baseFee;
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
uint64 LoadFeeTrack::scaleFeeBase(uint64 fee)
|
||||
uint64 LoadFeeTrack::scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
fee = mulDiv(fee, mBaseRef, mBaseFee);
|
||||
}
|
||||
|
||||
return fee;
|
||||
}
|
||||
|
||||
uint32 LoadFeeTrack::getBaseFee()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
return mBaseFee;
|
||||
return mulDiv(fee, referenceFeeUnits, baseFee);
|
||||
}
|
||||
|
||||
uint32 LoadFeeTrack::getRemoteFee()
|
||||
@@ -200,12 +187,6 @@ uint32 LoadFeeTrack::getLocalFee()
|
||||
return mLocalTxnLoadFee;
|
||||
}
|
||||
|
||||
uint32 LoadFeeTrack::getBaseRef()
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
return mBaseRef;
|
||||
}
|
||||
|
||||
void LoadFeeTrack::setRemoteFee(uint32 f)
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
@@ -233,7 +214,7 @@ void LoadFeeTrack::lowerLocalFee()
|
||||
mLocalTxnLoadFee = lftNormalFee;
|
||||
}
|
||||
|
||||
Json::Value LoadFeeTrack::getJson(int)
|
||||
Json::Value LoadFeeTrack::getJson(uint64 baseFee, uint32 referenceFeeUnits)
|
||||
{
|
||||
Json::Value j(Json::objectValue);
|
||||
|
||||
@@ -241,11 +222,11 @@ Json::Value LoadFeeTrack::getJson(int)
|
||||
boost::mutex::scoped_lock sl(mLock);
|
||||
|
||||
// base_fee = The cost to send a "reference" transaction under no load, in millionths of a Ripple
|
||||
j["base_fee"] = Json::Value::UInt(mBaseFee);
|
||||
j["base_fee"] = Json::Value::UInt(baseFee);
|
||||
|
||||
// load_fee = The cost to send a "reference" transaction now, in millionths of a Ripple
|
||||
j["load_fee"] = Json::Value::UInt(
|
||||
mulDiv(mBaseFee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
|
||||
mulDiv(baseFee, std::max(mLocalTxnLoadFee, mRemoteTxnLoadFee), lftNormalFee));
|
||||
}
|
||||
|
||||
return j;
|
||||
@@ -258,20 +239,20 @@ BOOST_AUTO_TEST_CASE(LoadFeeTrack_test)
|
||||
cLog(lsDEBUG) << "Running load fee track test";
|
||||
|
||||
Config d; // get a default configuration object
|
||||
LoadFeeTrack l(d.TRANSACTION_FEE_BASE, d.FEE_DEFAULT);
|
||||
LoadFeeTrack l;
|
||||
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(10000), 10000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000), 10000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(1), 1);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1), 1);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(10000, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeLoad(1, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
|
||||
|
||||
// Check new default fee values give same fees as old defaults
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_DEFAULT), 10);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_ACCOUNT_RESERVE), 200 * SYSTEM_CURRENCY_PARTS);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OWNER_RESERVE), 50 * SYSTEM_CURRENCY_PARTS);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_NICKNAME_CREATE), 1000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OFFER), 10);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_CONTRACT_OPERATION), 1);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_DEFAULT, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_ACCOUNT_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 200 * SYSTEM_CURRENCY_PARTS);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OWNER_RESERVE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 50 * SYSTEM_CURRENCY_PARTS);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_NICKNAME_CREATE, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1000);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_OFFER, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 10);
|
||||
BOOST_REQUIRE_EQUAL(l.scaleFeeBase(d.FEE_CONTRACT_OPERATION, d.FEE_DEFAULT, d.TRANSACTION_FEE_BASE), 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -123,32 +123,29 @@ protected:
|
||||
static const int lftFeeDecFraction = 16; // decrease fee by 1/16
|
||||
static const int lftFeeMax = lftNormalFee * 1000000;
|
||||
|
||||
uint32 mBaseRef; // The number of fee units a reference transaction costs
|
||||
uint32 mBaseFee; // The cost in millionths of a ripple of a reference transaction
|
||||
uint32 mLocalTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
uint32 mRemoteTxnLoadFee; // Scale factor, lftNormalFee = normal fee
|
||||
|
||||
boost::mutex mLock;
|
||||
|
||||
static uint64 mulDiv(uint64 value, uint32 mul, uint32 div);
|
||||
static uint64 mulDiv(uint64 value, uint32 mul, uint64 div);
|
||||
|
||||
public:
|
||||
|
||||
LoadFeeTrack(uint32 baseRef, uint32 baseFee) : mBaseRef(baseRef), mBaseFee(baseFee),
|
||||
mLocalTxnLoadFee(lftNormalFee), mRemoteTxnLoadFee(lftNormalFee)
|
||||
LoadFeeTrack() : mLocalTxnLoadFee(lftNormalFee), mRemoteTxnLoadFee(lftNormalFee)
|
||||
{ ; }
|
||||
|
||||
uint64 scaleFeeBase(uint64 fee); // Scale from fee units to millionths of a ripple
|
||||
uint64 scaleFeeLoad(uint64 fee); // Scale using load as well as base rate
|
||||
// Scale from fee units to millionths of a ripple
|
||||
uint64 scaleFeeBase(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits);
|
||||
|
||||
// Scale using load as well as base rate
|
||||
uint64 scaleFeeLoad(uint64 fee, uint64 baseFee, uint32 referenceFeeUnits);
|
||||
|
||||
uint32 getRemoteFee();
|
||||
uint32 getLocalFee();
|
||||
uint32 getBaseRef();
|
||||
uint32 getBaseFee();
|
||||
|
||||
Json::Value getJson(int);
|
||||
Json::Value getJson(uint64 baseFee, uint32 referenceFeeUnits);
|
||||
|
||||
void setBaseFee(uint32);
|
||||
void setRemoteFee(uint32);
|
||||
void raiseLocalFee();
|
||||
void lowerLocalFee();
|
||||
|
||||
@@ -331,7 +331,7 @@ TER OfferCreateTransactor::doApply()
|
||||
const STAmount saSrcXRPBalance = mTxnAccount->getFieldAmount(sfBalance);
|
||||
const uint32 uOwnerCount = mTxnAccount->getFieldU32(sfOwnerCount);
|
||||
// The reserve required to create the line.
|
||||
const uint64 uReserveCreate = theApp->scaleFeeBase(theConfig.FEE_ACCOUNT_RESERVE + uOwnerCount*theConfig.FEE_OWNER_RESERVE);
|
||||
const uint64 uReserveCreate = mEngine->getLedger()->getReserve(uOwnerCount);
|
||||
|
||||
if (saSrcXRPBalance.getNValue() < uReserveCreate) // Have enough reserve prior to creating offer?
|
||||
terResult = terINSUF_RESERVE_OFFER;
|
||||
|
||||
@@ -86,7 +86,7 @@ TER PaymentTransactor::doApply()
|
||||
return terNO_DST;
|
||||
}
|
||||
else if (isSetBit(mParams, tapOPEN_LEDGER) // Ledger is not final, can vote no.
|
||||
&& saDstAmount.getNValue() < theApp->scaleFeeBase(theConfig.FEE_ACCOUNT_RESERVE)) // Reserve is not scaled by load.
|
||||
&& saDstAmount.getNValue() < mEngine->getLedger()->getReserve(0)) // Reserve is not scaled by load.
|
||||
{
|
||||
cLog(lsINFO) << "doPayment: Delay transaction: Destination account does not exist. Insufficent payment to create account.";
|
||||
|
||||
@@ -141,7 +141,7 @@ TER PaymentTransactor::doApply()
|
||||
|
||||
const STAmount saSrcXRPBalance = mTxnAccount->getFieldAmount(sfBalance);
|
||||
const uint32 uOwnerCount = mTxnAccount->getFieldU32(sfOwnerCount);
|
||||
const uint64 uReserve = theApp->scaleFeeBase(theConfig.FEE_ACCOUNT_RESERVE + uOwnerCount * theConfig.FEE_OWNER_RESERVE);
|
||||
const uint64 uReserve = mEngine->getLedger()->getReserve(uOwnerCount);
|
||||
|
||||
// Make sure have enough reserve to send.
|
||||
if (isSetBit(mParams, tapOPEN_LEDGER) // Ledger is not final, we can vote.
|
||||
|
||||
@@ -59,7 +59,7 @@ TER TrustSetTransactor::doApply()
|
||||
const STAmount saSrcXRPBalance = mTxnAccount->getFieldAmount(sfBalance);
|
||||
const uint32 uOwnerCount = mTxnAccount->getFieldU32(sfOwnerCount);
|
||||
// The reserve required to create the line.
|
||||
const uint64 uReserveCreate = theApp->scaleFeeBase(theConfig.FEE_ACCOUNT_RESERVE + (uOwnerCount+1)* theConfig.FEE_OWNER_RESERVE);
|
||||
const uint64 uReserveCreate = mEngine->getLedger()->getReserve(uOwnerCount + 1);
|
||||
|
||||
STAmount saLimitAllow = saLimitAmount;
|
||||
saLimitAllow.setIssuer(mTxnAccountID);
|
||||
|
||||
Reference in New Issue
Block a user