mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Use XRPAmount for fees and ledger headers
This commit is contained in:
@@ -359,7 +359,7 @@ void Ledger::updateHash()
|
|||||||
info_.hash = sha512Half(
|
info_.hash = sha512Half(
|
||||||
HashPrefix::ledgerMaster,
|
HashPrefix::ledgerMaster,
|
||||||
std::uint32_t(info_.seq),
|
std::uint32_t(info_.seq),
|
||||||
std::uint64_t(info_.drops),
|
std::uint64_t(info_.drops.drops ()),
|
||||||
info_.parentHash,
|
info_.parentHash,
|
||||||
info_.txHash,
|
info_.txHash,
|
||||||
info_.accountHash,
|
info_.accountHash,
|
||||||
@@ -570,7 +570,7 @@ bool Ledger::saveValidatedLedger (bool current)
|
|||||||
*db << boost::str (
|
*db << boost::str (
|
||||||
addLedger %
|
addLedger %
|
||||||
to_string (getHash ()) % info_.seq % to_string (info_.parentHash) %
|
to_string (getHash ()) % info_.seq % to_string (info_.parentHash) %
|
||||||
std::to_string (info_.drops) % info_.closeTime %
|
to_string (info_.drops) % info_.closeTime %
|
||||||
info_.parentCloseTime % info_.closeTimeResolution %
|
info_.parentCloseTime % info_.closeTimeResolution %
|
||||||
info_.closeFlags % to_string (info_.accountHash) %
|
info_.closeFlags % to_string (info_.accountHash) %
|
||||||
to_string (info_.txHash));
|
to_string (info_.txHash));
|
||||||
|
|||||||
@@ -200,9 +200,9 @@ public:
|
|||||||
SLE> const& sle) override;
|
SLE> const& sle) override;
|
||||||
|
|
||||||
void
|
void
|
||||||
rawDestroyXRP (std::uint64_t feeDrops) override
|
rawDestroyXRP (XRPAmount const& fee) override
|
||||||
{
|
{
|
||||||
info_.drops -= feeDrops;
|
info_.drops -= fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <ripple/ledger/ApplyViewImpl.h>
|
#include <ripple/ledger/ApplyViewImpl.h>
|
||||||
#include <ripple/core/Config.h>
|
#include <ripple/core/Config.h>
|
||||||
#include <ripple/protocol/STTx.h>
|
#include <ripple/protocol/STTx.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
#include <beast/utility/Journal.h>
|
#include <beast/utility/Journal.h>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -92,9 +93,9 @@ public:
|
|||||||
std::shared_ptr <SLE const> const& after)> const& func);
|
std::shared_ptr <SLE const> const& after)> const& func);
|
||||||
|
|
||||||
void
|
void
|
||||||
destroyXRP (std::uint64_t feeDrops)
|
destroyXRP (XRPAmount const& fee)
|
||||||
{
|
{
|
||||||
view_->rawDestroyXRP(feeDrops);
|
view_->rawDestroyXRP(fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -38,10 +38,11 @@ Change::preflight (PreflightContext const& ctx)
|
|||||||
return temBAD_SRC_ACCOUNT;
|
return temBAD_SRC_ACCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const fee = ctx.tx.getTransactionFee ();
|
// No point in going any further if the transaction fee is malformed.
|
||||||
|
auto const fee = ctx.tx.getFieldAmount (sfFee);
|
||||||
if (!fee.native () || fee != beast::zero)
|
if (!fee.native () || fee != beast::zero)
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.warning) << "Change: Non-zero fee";
|
JLOG(ctx.j.warning) << "Change: invalid fee";
|
||||||
return temBAD_FEE;
|
return temBAD_FEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -539,20 +539,6 @@ CreateOffer::format_amount (STAmount const& amount)
|
|||||||
return txt;
|
return txt;
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
|
||||||
CreateOffer::getAccountReserve (SLE::pointer account)
|
|
||||||
{
|
|
||||||
// Mon Aug 17 11:00:00am PDT
|
|
||||||
static NetClock::time_point const switchoverTime (
|
|
||||||
std::chrono::seconds (493149600));
|
|
||||||
if (ctx_.view().info().parentCloseTime <=
|
|
||||||
switchoverTime.time_since_epoch().count())
|
|
||||||
return STAmount (ctx_.view().fees().accountReserve(
|
|
||||||
deprecatedWrongOwnerCount_+1));
|
|
||||||
return STAmount (ctx_.view().fees().accountReserve(
|
|
||||||
account->getFieldU32 (sfOwnerCount) + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateOffer::preCompute()
|
CreateOffer::preCompute()
|
||||||
{
|
{
|
||||||
@@ -784,18 +770,34 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel)
|
|||||||
return { tesSUCCESS, true };
|
return { tesSUCCESS, true };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPriorBalance < getAccountReserve (sleCreator))
|
|
||||||
{
|
{
|
||||||
// If we are here, the signing account had an insufficient reserve
|
// Mon Aug 17 11:00:00am PDT
|
||||||
// *prior* to our processing. If something actually crossed, then
|
static NetClock::time_point const switchoverTime (
|
||||||
// we allow this; otherwise, we just claim a fee.
|
std::chrono::seconds (493149600));
|
||||||
if (!crossed)
|
|
||||||
result = tecINSUF_RESERVE_OFFER;
|
|
||||||
|
|
||||||
if (result != tesSUCCESS)
|
XRPAmount reserve;
|
||||||
j_.debug << "final result: " << transToken (result);
|
|
||||||
|
|
||||||
return { result, true };
|
if (ctx_.view().info().parentCloseTime <=
|
||||||
|
switchoverTime.time_since_epoch().count())
|
||||||
|
reserve = ctx_.view().fees().accountReserve(
|
||||||
|
deprecatedWrongOwnerCount_+1);
|
||||||
|
else
|
||||||
|
reserve = ctx_.view().fees().accountReserve(
|
||||||
|
sleCreator->getFieldU32 (sfOwnerCount) + 1);
|
||||||
|
|
||||||
|
if (mPriorBalance < reserve)
|
||||||
|
{
|
||||||
|
// If we are here, the signing account had an insufficient reserve
|
||||||
|
// *prior* to our processing. If something actually crossed, then
|
||||||
|
// we allow this; otherwise, we just claim a fee.
|
||||||
|
if (!crossed)
|
||||||
|
result = tecINSUF_RESERVE_OFFER;
|
||||||
|
|
||||||
|
if (result != tesSUCCESS)
|
||||||
|
j_.debug << "final result: " << transToken (result);
|
||||||
|
|
||||||
|
return { result, true };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need to place the remainder of the offer into its order book.
|
// We need to place the remainder of the offer into its order book.
|
||||||
|
|||||||
@@ -49,11 +49,6 @@ public:
|
|||||||
TER
|
TER
|
||||||
preflight (PreflightContext const& ctx);
|
preflight (PreflightContext const& ctx);
|
||||||
|
|
||||||
/** Returns the reserve the account would have if an offer was added. */
|
|
||||||
// VFALCO This function is not needed just inline the behavior
|
|
||||||
STAmount
|
|
||||||
getAccountReserve (SLE::pointer account); // const?
|
|
||||||
|
|
||||||
void
|
void
|
||||||
preCompute() override;
|
preCompute() override;
|
||||||
|
|
||||||
|
|||||||
@@ -50,22 +50,21 @@ CreateTicket::preflight (PreflightContext const& ctx)
|
|||||||
return preflight2 (ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
|
||||||
CreateTicket::getAccountReserve (SLE::pointer account)
|
|
||||||
{
|
|
||||||
return STAmount (view().fees().accountReserve(
|
|
||||||
account->getFieldU32 (sfOwnerCount) + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
TER
|
TER
|
||||||
CreateTicket::doApply ()
|
CreateTicket::doApply ()
|
||||||
{
|
{
|
||||||
|
auto const sle = view().peek(keylet::account(account_));
|
||||||
|
|
||||||
// A ticket counts against the reserve of the issuing account, but we
|
// A ticket counts against the reserve of the issuing account, but we
|
||||||
// check the starting balance because we want to allow dipping into the
|
// check the starting balance because we want to allow dipping into the
|
||||||
// reserve to pay fees.
|
// reserve to pay fees.
|
||||||
if (mPriorBalance < STAmount(view().fees().accountReserve(
|
{
|
||||||
view().read(keylet::account(account_))->getFieldU32(sfOwnerCount) + 1)))
|
auto const reserve = view().fees().accountReserve(
|
||||||
return tecINSUFFICIENT_RESERVE;
|
sle->getFieldU32(sfOwnerCount) + 1);
|
||||||
|
|
||||||
|
if (mPriorBalance < reserve)
|
||||||
|
return tecINSUFFICIENT_RESERVE;
|
||||||
|
}
|
||||||
|
|
||||||
std::uint32_t expiration (0);
|
std::uint32_t expiration (0);
|
||||||
|
|
||||||
@@ -124,8 +123,7 @@ CreateTicket::doApply ()
|
|||||||
sleTicket->setFieldU64(sfOwnerNode, hint);
|
sleTicket->setFieldU64(sfOwnerNode, hint);
|
||||||
|
|
||||||
// If we succeeded, the new entry counts agains the creator's reserve.
|
// If we succeeded, the new entry counts agains the creator's reserve.
|
||||||
adjustOwnerCount(view(), view().peek(
|
adjustOwnerCount(view(), sle, 1);
|
||||||
keylet::account(account_)), 1);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,11 +40,6 @@ public:
|
|||||||
TER
|
TER
|
||||||
preflight (PreflightContext const& ctx);
|
preflight (PreflightContext const& ctx);
|
||||||
|
|
||||||
/** Returns the reserve the account would have if an offer was added. */
|
|
||||||
// VFALCO Not needed, just inline the behavior.
|
|
||||||
STAmount
|
|
||||||
getAccountReserve (SLE::pointer account);
|
|
||||||
|
|
||||||
TER doApply () override;
|
TER doApply () override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -380,6 +380,8 @@ Payment::doApply ()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert (saDstAmount.native ());
|
||||||
|
|
||||||
// Direct XRP payment.
|
// Direct XRP payment.
|
||||||
|
|
||||||
// uOwnerCount is the number of entries in this legder for this
|
// uOwnerCount is the number of entries in this legder for this
|
||||||
@@ -388,23 +390,22 @@ Payment::doApply ()
|
|||||||
keylet::account(account_))->getFieldU32 (sfOwnerCount);
|
keylet::account(account_))->getFieldU32 (sfOwnerCount);
|
||||||
|
|
||||||
// This is the total reserve in drops.
|
// This is the total reserve in drops.
|
||||||
auto const uReserve =
|
auto const reserve = view().fees().accountReserve(uOwnerCount);
|
||||||
view().fees().accountReserve(uOwnerCount);
|
|
||||||
|
|
||||||
// mPriorBalance is the balance on the sending account BEFORE the
|
// mPriorBalance is the balance on the sending account BEFORE the
|
||||||
// fees were charged. We want to make sure we have enough reserve
|
// fees were charged. We want to make sure we have enough reserve
|
||||||
// to send. Allow final spend to use reserve for fee.
|
// to send. Allow final spend to use reserve for fee.
|
||||||
auto const mmm = std::max(tx().getTransactionFee (),
|
auto const mmm = std::max(reserve,
|
||||||
STAmount (uReserve));
|
tx().getFieldAmount (sfFee).xrp ());
|
||||||
|
|
||||||
if (mPriorBalance < saDstAmount + mmm)
|
if (mPriorBalance < saDstAmount.xrp () + mmm)
|
||||||
{
|
{
|
||||||
// Vote no. However the transaction might succeed, if applied in
|
// Vote no. However the transaction might succeed, if applied in
|
||||||
// a different order.
|
// a different order.
|
||||||
j_.trace << "Delay transaction: Insufficient funds: " <<
|
j_.trace << "Delay transaction: Insufficient funds: " <<
|
||||||
" " << mPriorBalance.getText () <<
|
" " << to_string (mPriorBalance) <<
|
||||||
" / " << (saDstAmount + mmm).getText () <<
|
" / " << to_string (saDstAmount.xrp () + mmm) <<
|
||||||
" (" << uReserve << ")";
|
" (" << to_string (reserve) << ")";
|
||||||
|
|
||||||
terResult = tecUNFUNDED_PAYMENT;
|
terResult = tecUNFUNDED_PAYMENT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,8 +119,8 @@ SetTrust::doApply ()
|
|||||||
// to fund accounts in a way where there's no incentive to trick them
|
// to fund accounts in a way where there's no incentive to trick them
|
||||||
// into creating an account you have no intention of using.
|
// into creating an account you have no intention of using.
|
||||||
|
|
||||||
STAmount const reserveCreate ((uOwnerCount < 2)
|
XRPAmount const reserveCreate ((uOwnerCount < 2)
|
||||||
? 0
|
? XRPAmount (zero)
|
||||||
: view().fees().accountReserve(uOwnerCount + 1));
|
: view().fees().accountReserve(uOwnerCount + 1));
|
||||||
|
|
||||||
std::uint32_t uQualityIn (bQualityIn ? tx().getFieldU32 (sfQualityIn) : 0);
|
std::uint32_t uQualityIn (bQualityIn ? tx().getFieldU32 (sfQualityIn) : 0);
|
||||||
|
|||||||
@@ -183,23 +183,22 @@ SusPayCreate::doApply()
|
|||||||
return tecNO_PERMISSION;
|
return tecNO_PERMISSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
XRPAmount const amount =
|
|
||||||
STAmount(ctx_.tx[sfAmount]).mantissa();
|
|
||||||
|
|
||||||
auto const account = ctx_.tx[sfAccount];
|
auto const account = ctx_.tx[sfAccount];
|
||||||
|
|
||||||
auto const sle = ctx_.view().peek(
|
auto const sle = ctx_.view().peek(
|
||||||
keylet::account(account));
|
keylet::account(account));
|
||||||
|
|
||||||
if (XRPAmount(STAmount((*sle)[sfBalance]).mantissa()) <
|
// Check reserve and funds availability
|
||||||
XRPAmount(ctx_.view().fees().accountReserve(
|
{
|
||||||
(*sle)[sfOwnerCount] + 1)))
|
auto const balance = STAmount((*sle)[sfBalance]).xrp();
|
||||||
return tecINSUFFICIENT_RESERVE;
|
auto const reserve = ctx_.view().fees().accountReserve(
|
||||||
|
(*sle)[sfOwnerCount] + 1);
|
||||||
|
|
||||||
if (XRPAmount(STAmount((*sle)[sfBalance]).mantissa()) <
|
if (balance < reserve)
|
||||||
amount + XRPAmount(ctx_.view().fees().accountReserve(
|
return tecINSUFFICIENT_RESERVE;
|
||||||
(*sle)[sfOwnerCount] + 1)))
|
|
||||||
return tecUNFUNDED;
|
if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp())
|
||||||
|
return tecUNFUNDED;
|
||||||
|
}
|
||||||
|
|
||||||
// Check destination account
|
// Check destination account
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ preflight1 (PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// No point in going any further if the transaction fee is malformed.
|
// No point in going any further if the transaction fee is malformed.
|
||||||
auto const fee = ctx.tx.getTransactionFee ();
|
auto const fee = ctx.tx.getFieldAmount (sfFee);
|
||||||
if (!fee.native () || fee < beast::zero || !isLegalNet (fee))
|
if (!fee.native () || fee.negative () || !isLegalAmount (fee.xrp ()))
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.debug) << "preflight1: invalid fee";
|
JLOG(ctx.j.debug) << "preflight1: invalid fee";
|
||||||
return temBAD_FEE;
|
return temBAD_FEE;
|
||||||
@@ -114,30 +114,29 @@ std::uint64_t Transactor::calculateBaseFee ()
|
|||||||
|
|
||||||
TER Transactor::payFee ()
|
TER Transactor::payFee ()
|
||||||
{
|
{
|
||||||
STAmount saPaid = tx().getTransactionFee ();
|
auto const feePaid = tx().getFieldAmount (sfFee).xrp ();
|
||||||
|
if (!isLegalAmount (feePaid) || feePaid < beast::zero)
|
||||||
if (!isLegalNet (saPaid) || saPaid < zero)
|
|
||||||
return temBAD_FEE;
|
return temBAD_FEE;
|
||||||
|
|
||||||
// Only check fee is sufficient when the ledger is open.
|
// Only check fee is sufficient when the ledger is open.
|
||||||
if (view().open() && saPaid < mFeeDue)
|
if (view().open() && feePaid < mFeeDue)
|
||||||
{
|
{
|
||||||
JLOG(j_.trace) << "Insufficient fee paid: " <<
|
JLOG(j_.trace) << "Insufficient fee paid: " <<
|
||||||
saPaid.getText () << "/" << mFeeDue.getText ();
|
to_string (feePaid) << "/" << to_string (mFeeDue);
|
||||||
return telINSUF_FEE_P;
|
return telINSUF_FEE_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (saPaid == zero)
|
if (feePaid == zero)
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
|
|
||||||
auto const sle = view().peek(
|
auto const sle = view().peek(
|
||||||
keylet::account(account_));
|
keylet::account(account_));
|
||||||
|
|
||||||
if (mSourceBalance < saPaid)
|
if (mSourceBalance < feePaid)
|
||||||
{
|
{
|
||||||
JLOG(j_.trace) << "Insufficient balance:" <<
|
JLOG(j_.trace) << "Insufficient balance:" <<
|
||||||
" balance=" << mSourceBalance.getText () <<
|
" balance=" << to_string (mSourceBalance) <<
|
||||||
" paid=" << saPaid.getText ();
|
" paid=" << to_string (feePaid);
|
||||||
|
|
||||||
if ((mSourceBalance > zero) && ! view().open())
|
if ((mSourceBalance > zero) && ! view().open())
|
||||||
{
|
{
|
||||||
@@ -151,7 +150,7 @@ TER Transactor::payFee ()
|
|||||||
// Deduct the fee, so it's not available during the transaction.
|
// Deduct the fee, so it's not available during the transaction.
|
||||||
// Will only write the account back, if the transaction succeeds.
|
// Will only write the account back, if the transaction succeeds.
|
||||||
|
|
||||||
mSourceBalance -= saPaid;
|
mSourceBalance -= feePaid;
|
||||||
sle->setFieldAmount (sfBalance, mSourceBalance);
|
sle->setFieldAmount (sfBalance, mSourceBalance);
|
||||||
|
|
||||||
// VFALCO Should we call view().rawDestroyXRP() here as well?
|
// VFALCO Should we call view().rawDestroyXRP() here as well?
|
||||||
@@ -227,12 +226,12 @@ TER Transactor::apply ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto const& fees = view().fees();
|
auto const& fees = view().fees();
|
||||||
mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad(
|
mFeeDue = getApp().getFeeTrack().scaleFeeLoad(
|
||||||
calculateBaseFee(), fees.base, fees.units, view().flags() & tapADMIN));
|
calculateBaseFee(), fees.base, fees.units, view().flags() & tapADMIN);
|
||||||
|
|
||||||
if (sle)
|
if (sle)
|
||||||
{
|
{
|
||||||
mPriorBalance = sle->getFieldAmount (sfBalance);
|
mPriorBalance = STAmount ((*sle)[sfBalance]).xrp ();
|
||||||
mSourceBalance = mPriorBalance;
|
mSourceBalance = mPriorBalance;
|
||||||
mHasAuthKey = sle->isFieldPresent (sfRegularKey);
|
mHasAuthKey = sle->isFieldPresent (sfRegularKey);
|
||||||
|
|
||||||
@@ -550,7 +549,7 @@ Transactor::operator()()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool didApply = isTesSuccess (terResult);
|
bool didApply = isTesSuccess (terResult);
|
||||||
auto fee = tx().getTransactionFee ();
|
auto fee = tx().getFieldAmount(sfFee).xrp ();
|
||||||
|
|
||||||
if (ctx_.size() > 5200)
|
if (ctx_.size() > 5200)
|
||||||
terResult = tecOVERSIZE;
|
terResult = tecOVERSIZE;
|
||||||
@@ -602,7 +601,7 @@ Transactor::operator()()
|
|||||||
terResult = tefPAST_SEQ;
|
terResult = tefPAST_SEQ;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
STAmount balance = txnAcct->getFieldAmount (sfBalance);
|
auto const balance = txnAcct->getFieldAmount (sfBalance).xrp ();
|
||||||
|
|
||||||
// We retry/reject the transaction if the account
|
// We retry/reject the transaction if the account
|
||||||
// balance is zero or we're applying against an open
|
// balance is zero or we're applying against an open
|
||||||
@@ -645,23 +644,18 @@ Transactor::operator()()
|
|||||||
|
|
||||||
if(view().closed())
|
if(view().closed())
|
||||||
{
|
{
|
||||||
// VFALCO Fix this nonsense with Amount
|
// Charge whatever fee they specified.
|
||||||
// Charge whatever fee they specified. We break the
|
|
||||||
// encapsulation of STAmount here and use "special
|
|
||||||
// knowledge" - namely that a native amount is
|
|
||||||
// stored fully in the mantissa:
|
|
||||||
|
|
||||||
// The transactor guarantees these will never trigger
|
// The transactor guarantees this will never trigger
|
||||||
if (!fee.native () || fee.negative ())
|
if (fee < zero)
|
||||||
{
|
{
|
||||||
// VFALCO Log to journal here
|
// VFALCO Log to journal here
|
||||||
// JLOG(journal.fatal) << "invalid fee";
|
// JLOG(journal.fatal) << "invalid fee";
|
||||||
throw std::logic_error(
|
throw std::logic_error("amount is negative!");
|
||||||
"amount is negative!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fee != zero)
|
if (fee != zero)
|
||||||
ctx_.destroyXRP (fee.mantissa ());
|
ctx_.destroyXRP (fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_.apply(terResult);
|
ctx_.apply(terResult);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
|
#define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED
|
||||||
|
|
||||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
#include <beast/utility/Journal.h>
|
#include <beast/utility/Journal.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -57,9 +58,9 @@ protected:
|
|||||||
beast::Journal j_;
|
beast::Journal j_;
|
||||||
|
|
||||||
AccountID account_;
|
AccountID account_;
|
||||||
STAmount mFeeDue;
|
XRPAmount mFeeDue;
|
||||||
STAmount mPriorBalance; // Balance before fees.
|
XRPAmount mPriorBalance; // Balance before fees.
|
||||||
STAmount mSourceBalance; // Balance after fees.
|
XRPAmount mSourceBalance; // Balance after fees.
|
||||||
bool mHasAuthKey;
|
bool mHasAuthKey;
|
||||||
bool mSigMaster;
|
bool mSigMaster;
|
||||||
RippleAddress mSigningPubKey;
|
RippleAddress mSigningPubKey;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <ripple/ledger/RawView.h>
|
#include <ripple/ledger/RawView.h>
|
||||||
#include <ripple/ledger/ReadView.h>
|
#include <ripple/ledger/ReadView.h>
|
||||||
#include <ripple/ledger/detail/RawStateTable.h>
|
#include <ripple/ledger/detail/RawStateTable.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
@@ -209,7 +210,7 @@ public:
|
|||||||
|
|
||||||
void
|
void
|
||||||
rawDestroyXRP(
|
rawDestroyXRP(
|
||||||
std::uint64_t feeDrops) override;
|
XRPAmount const& fee) override;
|
||||||
|
|
||||||
// TxsRawView
|
// TxsRawView
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual
|
virtual
|
||||||
void
|
void
|
||||||
rawDestroyXRP (std::uint64_t feeDrops) = 0;
|
rawDestroyXRP (XRPAmount const& fee) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -23,9 +23,11 @@
|
|||||||
#include <ripple/ledger/detail/ReadViewFwdRange.h>
|
#include <ripple/ledger/detail/ReadViewFwdRange.h>
|
||||||
#include <ripple/basics/chrono.h>
|
#include <ripple/basics/chrono.h>
|
||||||
#include <ripple/protocol/Indexes.h>
|
#include <ripple/protocol/Indexes.h>
|
||||||
|
#include <ripple/protocol/IOUAmount.h>
|
||||||
#include <ripple/protocol/Protocol.h>
|
#include <ripple/protocol/Protocol.h>
|
||||||
#include <ripple/protocol/STLedgerEntry.h>
|
#include <ripple/protocol/STLedgerEntry.h>
|
||||||
#include <ripple/protocol/STTx.h>
|
#include <ripple/protocol/STTx.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
#include <beast/hash/uhash.h>
|
#include <beast/hash/uhash.h>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -56,10 +58,10 @@ struct Fees
|
|||||||
The reserve is calculated as the reserve base plus
|
The reserve is calculated as the reserve base plus
|
||||||
the reserve increment times the number of increments.
|
the reserve increment times the number of increments.
|
||||||
*/
|
*/
|
||||||
std::uint64_t
|
XRPAmount
|
||||||
accountReserve (std::size_t ownerCount) const
|
accountReserve (std::size_t ownerCount) const
|
||||||
{
|
{
|
||||||
return reserve + ownerCount * increment;
|
return { reserve + ownerCount * increment };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,7 +87,8 @@ struct LedgerInfo
|
|||||||
uint256 txHash = zero;
|
uint256 txHash = zero;
|
||||||
uint256 accountHash = zero;
|
uint256 accountHash = zero;
|
||||||
uint256 parentHash = zero;
|
uint256 parentHash = zero;
|
||||||
std::uint64_t drops = 0;
|
|
||||||
|
XRPAmount drops = zero;
|
||||||
|
|
||||||
// If validated is false, it means "not yet validated."
|
// If validated is false, it means "not yet validated."
|
||||||
// Once validated is true, it will never be set false at a later time.
|
// Once validated is true, it will never be set false at a later time.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <ripple/ledger/ReadView.h>
|
#include <ripple/ledger/ReadView.h>
|
||||||
#include <ripple/ledger/TxMeta.h>
|
#include <ripple/ledger/TxMeta.h>
|
||||||
#include <ripple/protocol/TER.h>
|
#include <ripple/protocol/TER.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
#include <beast/utility/Journal.h>
|
#include <beast/utility/Journal.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ private:
|
|||||||
std::pair<Action, std::shared_ptr<SLE>>>;
|
std::pair<Action, std::shared_ptr<SLE>>>;
|
||||||
|
|
||||||
items_t items_;
|
items_t items_;
|
||||||
std::uint64_t dropsDestroyed_ = 0;
|
XRPAmount dropsDestroyed_ = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ApplyStateTable() = default;
|
ApplyStateTable() = default;
|
||||||
@@ -126,7 +127,7 @@ public:
|
|||||||
std::shared_ptr<SLE> const& sle);
|
std::shared_ptr<SLE> const& sle);
|
||||||
|
|
||||||
void
|
void
|
||||||
destroyXRP (std::uint64_t feeDrops);
|
destroyXRP (XRPAmount const& fee);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Mods = hash_map<key_type,
|
using Mods = hash_map<key_type,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <ripple/ledger/OpenView.h>
|
#include <ripple/ledger/OpenView.h>
|
||||||
#include <ripple/ledger/ReadView.h>
|
#include <ripple/ledger/ReadView.h>
|
||||||
#include <ripple/ledger/detail/ApplyStateTable.h>
|
#include <ripple/ledger/detail/ApplyStateTable.h>
|
||||||
|
#include <ripple/protocol/XRPAmount.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -130,13 +131,13 @@ public:
|
|||||||
|
|
||||||
void
|
void
|
||||||
rawDestroyXRP (
|
rawDestroyXRP (
|
||||||
std::uint64_t feeDrops) override;
|
XRPAmount const& feeDrops) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ApplyFlags flags_;
|
ApplyFlags flags_;
|
||||||
ReadView const* base_;
|
ReadView const* base_;
|
||||||
detail::ApplyStateTable items_;
|
detail::ApplyStateTable items_;
|
||||||
std::uint64_t dropsDestroyed_ = 0;
|
XRPAmount dropsDestroyed_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public:
|
|||||||
Keylet const& k) const;
|
Keylet const& k) const;
|
||||||
|
|
||||||
void
|
void
|
||||||
destroyXRP (std::uint64_t feeDrops);
|
destroyXRP (XRPAmount const& fee);
|
||||||
|
|
||||||
std::unique_ptr<ReadView::sles_type::iter_base>
|
std::unique_ptr<ReadView::sles_type::iter_base>
|
||||||
slesBegin (ReadView const& base) const;
|
slesBegin (ReadView const& base) const;
|
||||||
@@ -97,7 +97,7 @@ private:
|
|||||||
std::pair<Action, std::shared_ptr<SLE>>>;
|
std::pair<Action, std::shared_ptr<SLE>>>;
|
||||||
|
|
||||||
items_t items_;
|
items_t items_;
|
||||||
std::uint64_t dropsDestroyed_ = 0;
|
XRPAmount dropsDestroyed_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -521,9 +521,9 @@ ApplyStateTable::update (ReadView const& base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ApplyStateTable::destroyXRP(std::uint64_t feeDrops)
|
ApplyStateTable::destroyXRP(XRPAmount const& fee)
|
||||||
{
|
{
|
||||||
dropsDestroyed_ += feeDrops;
|
dropsDestroyed_ += fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -173,9 +173,9 @@ ApplyViewBase::rawReplace(
|
|||||||
|
|
||||||
void
|
void
|
||||||
ApplyViewBase::rawDestroyXRP(
|
ApplyViewBase::rawDestroyXRP(
|
||||||
std::uint64_t feeDrops)
|
XRPAmount const& fee)
|
||||||
{
|
{
|
||||||
items_.destroyXRP(feeDrops);
|
items_.destroyXRP(fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|||||||
@@ -247,9 +247,9 @@ OpenView::rawReplace(
|
|||||||
|
|
||||||
void
|
void
|
||||||
OpenView::rawDestroyXRP(
|
OpenView::rawDestroyXRP(
|
||||||
std::uint64_t feeDrops)
|
XRPAmount const& fee)
|
||||||
{
|
{
|
||||||
items_.destroyXRP(feeDrops);
|
items_.destroyXRP(fee);
|
||||||
// VFALCO Deduct from info_.totalDrops ?
|
// VFALCO Deduct from info_.totalDrops ?
|
||||||
// What about child views?
|
// What about child views?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -333,9 +333,9 @@ RawStateTable::read (ReadView const& base,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RawStateTable::destroyXRP(std::uint64_t feeDrops)
|
RawStateTable::destroyXRP(XRPAmount const& fee)
|
||||||
{
|
{
|
||||||
dropsDestroyed_ += feeDrops;
|
dropsDestroyed_ += fee;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ReadView::sles_type::iter_base>
|
std::unique_ptr<ReadView::sles_type::iter_base>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace ripple {
|
|||||||
void addRaw (LedgerInfo const& info, Serializer& s)
|
void addRaw (LedgerInfo const& info, Serializer& s)
|
||||||
{
|
{
|
||||||
s.add32 (info.seq);
|
s.add32 (info.seq);
|
||||||
s.add64 (info.drops);
|
s.add64 (info.drops.drops ());
|
||||||
s.add256 (info.parentHash);
|
s.add256 (info.parentHash);
|
||||||
s.add256 (info.txHash);
|
s.add256 (info.txHash);
|
||||||
s.add256 (info.accountHash);
|
s.add256 (info.accountHash);
|
||||||
@@ -109,10 +109,10 @@ accountHolds (ReadView const& view,
|
|||||||
auto const sle = view.read(
|
auto const sle = view.read(
|
||||||
keylet::account(account));
|
keylet::account(account));
|
||||||
auto const reserve =
|
auto const reserve =
|
||||||
STAmount{view.fees().accountReserve(
|
view.fees().accountReserve(
|
||||||
sle->getFieldU32(sfOwnerCount))};
|
sle->getFieldU32(sfOwnerCount));
|
||||||
auto const balance =
|
auto const balance =
|
||||||
sle->getFieldAmount(sfBalance);
|
sle->getFieldAmount(sfBalance).xrp ();
|
||||||
if (balance < reserve)
|
if (balance < reserve)
|
||||||
amount.clear ();
|
amount.clear ();
|
||||||
else
|
else
|
||||||
@@ -120,8 +120,8 @@ accountHolds (ReadView const& view,
|
|||||||
WriteLog (lsTRACE, View) << "accountHolds:" <<
|
WriteLog (lsTRACE, View) << "accountHolds:" <<
|
||||||
" account=" << to_string (account) <<
|
" account=" << to_string (account) <<
|
||||||
" amount=" << amount.getFullText () <<
|
" amount=" << amount.getFullText () <<
|
||||||
" balance=" << balance.getFullText () <<
|
" balance=" << to_string (balance) <<
|
||||||
" reserve=" << reserve.getFullText ();
|
" reserve=" << to_string (reserve);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -203,6 +203,12 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STAmount& operator= (XRPAmount const& amount)
|
||||||
|
{
|
||||||
|
*this = STAmount (amount);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Modification
|
// Modification
|
||||||
|
|||||||
@@ -88,14 +88,6 @@ public:
|
|||||||
{
|
{
|
||||||
return tx_type_;
|
return tx_type_;
|
||||||
}
|
}
|
||||||
STAmount getTransactionFee () const
|
|
||||||
{
|
|
||||||
return getFieldAmount (sfFee);
|
|
||||||
}
|
|
||||||
void setTransactionFee (const STAmount & fee)
|
|
||||||
{
|
|
||||||
setFieldAmount (sfFee, fee);
|
|
||||||
}
|
|
||||||
|
|
||||||
Blob getSigningPubKey () const
|
Blob getSigningPubKey () const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1087,12 +1087,21 @@ Json::Value transactionSubmitMultiSigned (
|
|||||||
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Fee field must be greater than zero.
|
// The Fee field must be in XRP and greater than zero.
|
||||||
if (stpTrans->getFieldAmount (sfFee) <= 0)
|
auto const fee = stpTrans->getFieldAmount (sfFee);
|
||||||
|
|
||||||
|
if (!isLegalNet (fee))
|
||||||
{
|
{
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
err << "Invalid " << sfFee.fieldName
|
err << "Invalid " << sfFee.fieldName
|
||||||
<< " field. Value must be greater than zero.";
|
<< " field. Fees must be specified in XRP.";
|
||||||
|
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
||||||
|
}
|
||||||
|
if (fee <= 0)
|
||||||
|
{
|
||||||
|
std::ostringstream err;
|
||||||
|
err << "Invalid " << sfFee.fieldName
|
||||||
|
<< " field. Fees must be greater than zero.";
|
||||||
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
return RPC::make_error (rpcINVALID_PARAMS, err.str ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user