diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 16c5da987..eda631e86 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -359,7 +359,7 @@ void Ledger::updateHash() info_.hash = sha512Half( HashPrefix::ledgerMaster, std::uint32_t(info_.seq), - std::uint64_t(info_.drops), + std::uint64_t(info_.drops.drops ()), info_.parentHash, info_.txHash, info_.accountHash, @@ -570,7 +570,7 @@ bool Ledger::saveValidatedLedger (bool current) *db << boost::str ( addLedger % 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_.closeFlags % to_string (info_.accountHash) % to_string (info_.txHash)); diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index ce928c29e..eab3c1dfd 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -200,9 +200,9 @@ public: SLE> const& sle) override; void - rawDestroyXRP (std::uint64_t feeDrops) override + rawDestroyXRP (XRPAmount const& fee) override { - info_.drops -= feeDrops; + info_.drops -= fee; } // diff --git a/src/ripple/app/tx/impl/ApplyContext.h b/src/ripple/app/tx/impl/ApplyContext.h index 8d9498548..4fbb7da18 100644 --- a/src/ripple/app/tx/impl/ApplyContext.h +++ b/src/ripple/app/tx/impl/ApplyContext.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -92,9 +93,9 @@ public: std::shared_ptr const& after)> const& func); void - destroyXRP (std::uint64_t feeDrops) + destroyXRP (XRPAmount const& fee) { - view_->rawDestroyXRP(feeDrops); + view_->rawDestroyXRP(fee); } private: diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index af14074fe..b307a26eb 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -38,10 +38,11 @@ Change::preflight (PreflightContext const& ctx) 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) { - JLOG(ctx.j.warning) << "Change: Non-zero fee"; + JLOG(ctx.j.warning) << "Change: invalid fee"; return temBAD_FEE; } diff --git a/src/ripple/app/tx/impl/CreateOffer.cpp b/src/ripple/app/tx/impl/CreateOffer.cpp index b81d37a0f..7885c4ed3 100644 --- a/src/ripple/app/tx/impl/CreateOffer.cpp +++ b/src/ripple/app/tx/impl/CreateOffer.cpp @@ -539,20 +539,6 @@ CreateOffer::format_amount (STAmount const& amount) 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 CreateOffer::preCompute() { @@ -784,18 +770,34 @@ CreateOffer::applyGuts (ApplyView& view, ApplyView& view_cancel) return { tesSUCCESS, true }; } - if (mPriorBalance < getAccountReserve (sleCreator)) { - // 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; + // Mon Aug 17 11:00:00am PDT + static NetClock::time_point const switchoverTime ( + std::chrono::seconds (493149600)); - if (result != tesSUCCESS) - j_.debug << "final result: " << transToken (result); + XRPAmount reserve; - 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. diff --git a/src/ripple/app/tx/impl/CreateOffer.h b/src/ripple/app/tx/impl/CreateOffer.h index b1cd5b45e..44abba2f9 100644 --- a/src/ripple/app/tx/impl/CreateOffer.h +++ b/src/ripple/app/tx/impl/CreateOffer.h @@ -49,11 +49,6 @@ public: TER 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 preCompute() override; diff --git a/src/ripple/app/tx/impl/CreateTicket.cpp b/src/ripple/app/tx/impl/CreateTicket.cpp index a05a32f61..b04e6657f 100644 --- a/src/ripple/app/tx/impl/CreateTicket.cpp +++ b/src/ripple/app/tx/impl/CreateTicket.cpp @@ -50,22 +50,21 @@ CreateTicket::preflight (PreflightContext const& ctx) return preflight2 (ctx); } -STAmount -CreateTicket::getAccountReserve (SLE::pointer account) -{ - return STAmount (view().fees().accountReserve( - account->getFieldU32 (sfOwnerCount) + 1)); -} - TER CreateTicket::doApply () { + auto const sle = view().peek(keylet::account(account_)); + // A ticket counts against the reserve of the issuing account, but we // check the starting balance because we want to allow dipping into the // reserve to pay fees. - if (mPriorBalance < STAmount(view().fees().accountReserve( - view().read(keylet::account(account_))->getFieldU32(sfOwnerCount) + 1))) - return tecINSUFFICIENT_RESERVE; + { + auto const reserve = view().fees().accountReserve( + sle->getFieldU32(sfOwnerCount) + 1); + + if (mPriorBalance < reserve) + return tecINSUFFICIENT_RESERVE; + } std::uint32_t expiration (0); @@ -124,8 +123,7 @@ CreateTicket::doApply () sleTicket->setFieldU64(sfOwnerNode, hint); // If we succeeded, the new entry counts agains the creator's reserve. - adjustOwnerCount(view(), view().peek( - keylet::account(account_)), 1); + adjustOwnerCount(view(), sle, 1); return result; } diff --git a/src/ripple/app/tx/impl/CreateTicket.h b/src/ripple/app/tx/impl/CreateTicket.h index 3922d537f..57db3cad2 100644 --- a/src/ripple/app/tx/impl/CreateTicket.h +++ b/src/ripple/app/tx/impl/CreateTicket.h @@ -40,11 +40,6 @@ public: TER 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; }; diff --git a/src/ripple/app/tx/impl/Payment.cpp b/src/ripple/app/tx/impl/Payment.cpp index 3c0d1ebfa..0d2f2c888 100644 --- a/src/ripple/app/tx/impl/Payment.cpp +++ b/src/ripple/app/tx/impl/Payment.cpp @@ -380,6 +380,8 @@ Payment::doApply () } else { + assert (saDstAmount.native ()); + // Direct XRP payment. // uOwnerCount is the number of entries in this legder for this @@ -388,23 +390,22 @@ Payment::doApply () keylet::account(account_))->getFieldU32 (sfOwnerCount); // This is the total reserve in drops. - auto const uReserve = - view().fees().accountReserve(uOwnerCount); + auto const reserve = view().fees().accountReserve(uOwnerCount); // mPriorBalance is the balance on the sending account BEFORE the // fees were charged. We want to make sure we have enough reserve // to send. Allow final spend to use reserve for fee. - auto const mmm = std::max(tx().getTransactionFee (), - STAmount (uReserve)); + auto const mmm = std::max(reserve, + tx().getFieldAmount (sfFee).xrp ()); - if (mPriorBalance < saDstAmount + mmm) + if (mPriorBalance < saDstAmount.xrp () + mmm) { // Vote no. However the transaction might succeed, if applied in // a different order. j_.trace << "Delay transaction: Insufficient funds: " << - " " << mPriorBalance.getText () << - " / " << (saDstAmount + mmm).getText () << - " (" << uReserve << ")"; + " " << to_string (mPriorBalance) << + " / " << to_string (saDstAmount.xrp () + mmm) << + " (" << to_string (reserve) << ")"; terResult = tecUNFUNDED_PAYMENT; } diff --git a/src/ripple/app/tx/impl/SetTrust.cpp b/src/ripple/app/tx/impl/SetTrust.cpp index 1d123eee2..405288d12 100644 --- a/src/ripple/app/tx/impl/SetTrust.cpp +++ b/src/ripple/app/tx/impl/SetTrust.cpp @@ -119,8 +119,8 @@ SetTrust::doApply () // to fund accounts in a way where there's no incentive to trick them // into creating an account you have no intention of using. - STAmount const reserveCreate ((uOwnerCount < 2) - ? 0 + XRPAmount const reserveCreate ((uOwnerCount < 2) + ? XRPAmount (zero) : view().fees().accountReserve(uOwnerCount + 1)); std::uint32_t uQualityIn (bQualityIn ? tx().getFieldU32 (sfQualityIn) : 0); diff --git a/src/ripple/app/tx/impl/SusPay.cpp b/src/ripple/app/tx/impl/SusPay.cpp index 87e0fdb23..6171d2bdc 100644 --- a/src/ripple/app/tx/impl/SusPay.cpp +++ b/src/ripple/app/tx/impl/SusPay.cpp @@ -183,23 +183,22 @@ SusPayCreate::doApply() return tecNO_PERMISSION; } - XRPAmount const amount = - STAmount(ctx_.tx[sfAmount]).mantissa(); - auto const account = ctx_.tx[sfAccount]; - auto const sle = ctx_.view().peek( keylet::account(account)); - if (XRPAmount(STAmount((*sle)[sfBalance]).mantissa()) < - XRPAmount(ctx_.view().fees().accountReserve( - (*sle)[sfOwnerCount] + 1))) - return tecINSUFFICIENT_RESERVE; + // Check reserve and funds availability + { + auto const balance = STAmount((*sle)[sfBalance]).xrp(); + auto const reserve = ctx_.view().fees().accountReserve( + (*sle)[sfOwnerCount] + 1); - if (XRPAmount(STAmount((*sle)[sfBalance]).mantissa()) < - amount + XRPAmount(ctx_.view().fees().accountReserve( - (*sle)[sfOwnerCount] + 1))) - return tecUNFUNDED; + if (balance < reserve) + return tecINSUFFICIENT_RESERVE; + + if (balance < reserve + STAmount(ctx_.tx[sfAmount]).xrp()) + return tecUNFUNDED; + } // Check destination account { diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index ef5905f68..e05b220bd 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -44,8 +44,8 @@ preflight1 (PreflightContext const& ctx) } // No point in going any further if the transaction fee is malformed. - auto const fee = ctx.tx.getTransactionFee (); - if (!fee.native () || fee < beast::zero || !isLegalNet (fee)) + auto const fee = ctx.tx.getFieldAmount (sfFee); + if (!fee.native () || fee.negative () || !isLegalAmount (fee.xrp ())) { JLOG(ctx.j.debug) << "preflight1: invalid fee"; return temBAD_FEE; @@ -114,30 +114,29 @@ std::uint64_t Transactor::calculateBaseFee () TER Transactor::payFee () { - STAmount saPaid = tx().getTransactionFee (); - - if (!isLegalNet (saPaid) || saPaid < zero) + auto const feePaid = tx().getFieldAmount (sfFee).xrp (); + if (!isLegalAmount (feePaid) || feePaid < beast::zero) return temBAD_FEE; // 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: " << - saPaid.getText () << "/" << mFeeDue.getText (); + to_string (feePaid) << "/" << to_string (mFeeDue); return telINSUF_FEE_P; } - if (saPaid == zero) + if (feePaid == zero) return tesSUCCESS; auto const sle = view().peek( keylet::account(account_)); - if (mSourceBalance < saPaid) + if (mSourceBalance < feePaid) { JLOG(j_.trace) << "Insufficient balance:" << - " balance=" << mSourceBalance.getText () << - " paid=" << saPaid.getText (); + " balance=" << to_string (mSourceBalance) << + " paid=" << to_string (feePaid); if ((mSourceBalance > zero) && ! view().open()) { @@ -151,7 +150,7 @@ TER Transactor::payFee () // Deduct the fee, so it's not available during the transaction. // Will only write the account back, if the transaction succeeds. - mSourceBalance -= saPaid; + mSourceBalance -= feePaid; sle->setFieldAmount (sfBalance, mSourceBalance); // VFALCO Should we call view().rawDestroyXRP() here as well? @@ -227,12 +226,12 @@ TER Transactor::apply () } auto const& fees = view().fees(); - mFeeDue = STAmount (getApp().getFeeTrack().scaleFeeLoad( - calculateBaseFee(), fees.base, fees.units, view().flags() & tapADMIN)); + mFeeDue = getApp().getFeeTrack().scaleFeeLoad( + calculateBaseFee(), fees.base, fees.units, view().flags() & tapADMIN); if (sle) { - mPriorBalance = sle->getFieldAmount (sfBalance); + mPriorBalance = STAmount ((*sle)[sfBalance]).xrp (); mSourceBalance = mPriorBalance; mHasAuthKey = sle->isFieldPresent (sfRegularKey); @@ -550,7 +549,7 @@ Transactor::operator()() } bool didApply = isTesSuccess (terResult); - auto fee = tx().getTransactionFee (); + auto fee = tx().getFieldAmount(sfFee).xrp (); if (ctx_.size() > 5200) terResult = tecOVERSIZE; @@ -602,7 +601,7 @@ Transactor::operator()() terResult = tefPAST_SEQ; else { - STAmount balance = txnAcct->getFieldAmount (sfBalance); + auto const balance = txnAcct->getFieldAmount (sfBalance).xrp (); // We retry/reject the transaction if the account // balance is zero or we're applying against an open @@ -645,23 +644,18 @@ Transactor::operator()() if(view().closed()) { - // VFALCO Fix this nonsense with Amount - // 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: + // Charge whatever fee they specified. - // The transactor guarantees these will never trigger - if (!fee.native () || fee.negative ()) + // The transactor guarantees this will never trigger + if (fee < zero) { // VFALCO Log to journal here // JLOG(journal.fatal) << "invalid fee"; - throw std::logic_error( - "amount is negative!"); + throw std::logic_error("amount is negative!"); } if (fee != zero) - ctx_.destroyXRP (fee.mantissa ()); + ctx_.destroyXRP (fee); } ctx_.apply(terResult); diff --git a/src/ripple/app/tx/impl/Transactor.h b/src/ripple/app/tx/impl/Transactor.h index c14bce293..65245ddb1 100644 --- a/src/ripple/app/tx/impl/Transactor.h +++ b/src/ripple/app/tx/impl/Transactor.h @@ -21,6 +21,7 @@ #define RIPPLE_APP_TX_TRANSACTOR_H_INCLUDED #include +#include #include namespace ripple { @@ -57,9 +58,9 @@ protected: beast::Journal j_; AccountID account_; - STAmount mFeeDue; - STAmount mPriorBalance; // Balance before fees. - STAmount mSourceBalance; // Balance after fees. + XRPAmount mFeeDue; + XRPAmount mPriorBalance; // Balance before fees. + XRPAmount mSourceBalance; // Balance after fees. bool mHasAuthKey; bool mSigMaster; RippleAddress mSigningPubKey; diff --git a/src/ripple/ledger/OpenView.h b/src/ripple/ledger/OpenView.h index 423e7ff7f..7caee53a8 100644 --- a/src/ripple/ledger/OpenView.h +++ b/src/ripple/ledger/OpenView.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace ripple { @@ -209,7 +210,7 @@ public: void rawDestroyXRP( - std::uint64_t feeDrops) override; + XRPAmount const& fee) override; // TxsRawView diff --git a/src/ripple/ledger/RawView.h b/src/ripple/ledger/RawView.h index edb4e8799..ffe9f6ff3 100644 --- a/src/ripple/ledger/RawView.h +++ b/src/ripple/ledger/RawView.h @@ -85,7 +85,7 @@ public: */ virtual void - rawDestroyXRP (std::uint64_t feeDrops) = 0; + rawDestroyXRP (XRPAmount const& fee) = 0; }; //------------------------------------------------------------------------------ diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index ff274a256..d40d681cd 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -23,9 +23,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -56,10 +58,10 @@ struct Fees The reserve is calculated as the reserve base plus the reserve increment times the number of increments. */ - std::uint64_t + XRPAmount accountReserve (std::size_t ownerCount) const { - return reserve + ownerCount * increment; + return { reserve + ownerCount * increment }; } }; @@ -85,7 +87,8 @@ struct LedgerInfo uint256 txHash = zero; uint256 accountHash = zero; uint256 parentHash = zero; - std::uint64_t drops = 0; + + XRPAmount drops = zero; // If validated is false, it means "not yet validated." // Once validated is true, it will never be set false at a later time. diff --git a/src/ripple/ledger/detail/ApplyStateTable.h b/src/ripple/ledger/detail/ApplyStateTable.h index dbbd2c6b3..83a34e14d 100644 --- a/src/ripple/ledger/detail/ApplyStateTable.h +++ b/src/ripple/ledger/detail/ApplyStateTable.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,7 @@ private: std::pair>>; items_t items_; - std::uint64_t dropsDestroyed_ = 0; + XRPAmount dropsDestroyed_ = 0; public: ApplyStateTable() = default; @@ -126,7 +127,7 @@ public: std::shared_ptr const& sle); void - destroyXRP (std::uint64_t feeDrops); + destroyXRP (XRPAmount const& fee); private: using Mods = hash_map #include #include +#include namespace ripple { namespace detail { @@ -130,13 +131,13 @@ public: void rawDestroyXRP ( - std::uint64_t feeDrops) override; + XRPAmount const& feeDrops) override; protected: ApplyFlags flags_; ReadView const* base_; detail::ApplyStateTable items_; - std::uint64_t dropsDestroyed_ = 0; + XRPAmount dropsDestroyed_ = 0; }; } // detail diff --git a/src/ripple/ledger/detail/RawStateTable.h b/src/ripple/ledger/detail/RawStateTable.h index e7064fa3a..f71470741 100644 --- a/src/ripple/ledger/detail/RawStateTable.h +++ b/src/ripple/ledger/detail/RawStateTable.h @@ -75,7 +75,7 @@ public: Keylet const& k) const; void - destroyXRP (std::uint64_t feeDrops); + destroyXRP (XRPAmount const& fee); std::unique_ptr slesBegin (ReadView const& base) const; @@ -97,7 +97,7 @@ private: std::pair>>; items_t items_; - std::uint64_t dropsDestroyed_ = 0; + XRPAmount dropsDestroyed_ = 0; }; } // detail diff --git a/src/ripple/ledger/impl/ApplyStateTable.cpp b/src/ripple/ledger/impl/ApplyStateTable.cpp index 93e8d52b6..876810071 100644 --- a/src/ripple/ledger/impl/ApplyStateTable.cpp +++ b/src/ripple/ledger/impl/ApplyStateTable.cpp @@ -521,9 +521,9 @@ ApplyStateTable::update (ReadView const& base, } void -ApplyStateTable::destroyXRP(std::uint64_t feeDrops) +ApplyStateTable::destroyXRP(XRPAmount const& fee) { - dropsDestroyed_ += feeDrops; + dropsDestroyed_ += fee; } //------------------------------------------------------------------------------ diff --git a/src/ripple/ledger/impl/ApplyViewBase.cpp b/src/ripple/ledger/impl/ApplyViewBase.cpp index 22491d4ca..ee529451b 100644 --- a/src/ripple/ledger/impl/ApplyViewBase.cpp +++ b/src/ripple/ledger/impl/ApplyViewBase.cpp @@ -173,9 +173,9 @@ ApplyViewBase::rawReplace( void ApplyViewBase::rawDestroyXRP( - std::uint64_t feeDrops) + XRPAmount const& fee) { - items_.destroyXRP(feeDrops); + items_.destroyXRP(fee); } } // detail diff --git a/src/ripple/ledger/impl/OpenView.cpp b/src/ripple/ledger/impl/OpenView.cpp index 01a31396b..d2380e5f9 100644 --- a/src/ripple/ledger/impl/OpenView.cpp +++ b/src/ripple/ledger/impl/OpenView.cpp @@ -247,9 +247,9 @@ OpenView::rawReplace( void OpenView::rawDestroyXRP( - std::uint64_t feeDrops) + XRPAmount const& fee) { - items_.destroyXRP(feeDrops); + items_.destroyXRP(fee); // VFALCO Deduct from info_.totalDrops ? // What about child views? } diff --git a/src/ripple/ledger/impl/RawStateTable.cpp b/src/ripple/ledger/impl/RawStateTable.cpp index e47d7f82f..2e5353565 100644 --- a/src/ripple/ledger/impl/RawStateTable.cpp +++ b/src/ripple/ledger/impl/RawStateTable.cpp @@ -333,9 +333,9 @@ RawStateTable::read (ReadView const& base, } void -RawStateTable::destroyXRP(std::uint64_t feeDrops) +RawStateTable::destroyXRP(XRPAmount const& fee) { - dropsDestroyed_ += feeDrops; + dropsDestroyed_ += fee; } std::unique_ptr diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index 533f4d507..1e393ed0a 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -47,7 +47,7 @@ namespace ripple { void addRaw (LedgerInfo const& info, Serializer& s) { s.add32 (info.seq); - s.add64 (info.drops); + s.add64 (info.drops.drops ()); s.add256 (info.parentHash); s.add256 (info.txHash); s.add256 (info.accountHash); @@ -109,10 +109,10 @@ accountHolds (ReadView const& view, auto const sle = view.read( keylet::account(account)); auto const reserve = - STAmount{view.fees().accountReserve( - sle->getFieldU32(sfOwnerCount))}; + view.fees().accountReserve( + sle->getFieldU32(sfOwnerCount)); auto const balance = - sle->getFieldAmount(sfBalance); + sle->getFieldAmount(sfBalance).xrp (); if (balance < reserve) amount.clear (); else @@ -120,8 +120,8 @@ accountHolds (ReadView const& view, WriteLog (lsTRACE, View) << "accountHolds:" << " account=" << to_string (account) << " amount=" << amount.getFullText () << - " balance=" << balance.getFullText () << - " reserve=" << reserve.getFullText (); + " balance=" << to_string (balance) << + " reserve=" << to_string (reserve); } else { diff --git a/src/ripple/protocol/STAmount.h b/src/ripple/protocol/STAmount.h index b9d5ad8fb..b22cc0f27 100644 --- a/src/ripple/protocol/STAmount.h +++ b/src/ripple/protocol/STAmount.h @@ -203,6 +203,12 @@ public: return *this; } + STAmount& operator= (XRPAmount const& amount) + { + *this = STAmount (amount); + return *this; + } + //-------------------------------------------------------------------------- // // Modification diff --git a/src/ripple/protocol/STTx.h b/src/ripple/protocol/STTx.h index 6a7a4c731..84fa4de42 100644 --- a/src/ripple/protocol/STTx.h +++ b/src/ripple/protocol/STTx.h @@ -88,14 +88,6 @@ public: { return tx_type_; } - STAmount getTransactionFee () const - { - return getFieldAmount (sfFee); - } - void setTransactionFee (const STAmount & fee) - { - setFieldAmount (sfFee, fee); - } Blob getSigningPubKey () const { diff --git a/src/ripple/rpc/impl/TransactionSign.cpp b/src/ripple/rpc/impl/TransactionSign.cpp index d5fbd0a4b..f8c4a890f 100644 --- a/src/ripple/rpc/impl/TransactionSign.cpp +++ b/src/ripple/rpc/impl/TransactionSign.cpp @@ -1087,12 +1087,21 @@ Json::Value transactionSubmitMultiSigned ( return RPC::make_error (rpcINVALID_PARAMS, err.str ()); } - // The Fee field must be greater than zero. - if (stpTrans->getFieldAmount (sfFee) <= 0) + // The Fee field must be in XRP and greater than zero. + auto const fee = stpTrans->getFieldAmount (sfFee); + + if (!isLegalNet (fee)) { std::ostringstream err; 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 ()); } }