mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 02:55:50 +00:00
Validate fee during preflight
This commit is contained in:
@@ -29,6 +29,10 @@ namespace ripple {
|
|||||||
TER
|
TER
|
||||||
CancelOffer::preflight (PreflightContext const& ctx)
|
CancelOffer::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto const uTxFlags = ctx.tx.getFlags();
|
auto const uTxFlags = ctx.tx.getFlags();
|
||||||
|
|
||||||
if (uTxFlags & tfUniversalMask)
|
if (uTxFlags & tfUniversalMask)
|
||||||
@@ -46,7 +50,7 @@ CancelOffer::preflight (PreflightContext const& ctx)
|
|||||||
return temBAD_SEQUENCE;
|
return temBAD_SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -32,7 +32,12 @@ CancelTicket::preflight (PreflightContext const& ctx)
|
|||||||
if (! (ctx.flags & tapENABLE_TESTING))
|
if (! (ctx.flags & tapENABLE_TESTING))
|
||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
#endif
|
#endif
|
||||||
return Transactor::preflight(ctx);
|
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -32,13 +32,19 @@ TER
|
|||||||
Change::preflight (PreflightContext const& ctx)
|
Change::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
auto account = ctx.tx.getAccountID(sfAccount);
|
auto account = ctx.tx.getAccountID(sfAccount);
|
||||||
|
if (account != zero)
|
||||||
if (account.isNonZero ())
|
|
||||||
{
|
{
|
||||||
JLOG(ctx.j.warning) << "Bad source id";
|
JLOG(ctx.j.warning) << "Bad source id";
|
||||||
return temBAD_SRC_ACCOUNT;
|
return temBAD_SRC_ACCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto const fee = ctx.tx.getTransactionFee ();
|
||||||
|
if (!fee.native () || fee != beast::zero)
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.warning) << "Non-zero fee";
|
||||||
|
return temBAD_FEE;
|
||||||
|
}
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +95,7 @@ Change::checkSeq()
|
|||||||
TER
|
TER
|
||||||
Change::payFee()
|
Change::payFee()
|
||||||
{
|
{
|
||||||
if (tx().getTransactionFee () != STAmount ())
|
if (tx().getTransactionFee () != beast::zero)
|
||||||
{
|
{
|
||||||
j_.warning << "Non-zero fee";
|
j_.warning << "Non-zero fee";
|
||||||
return temBAD_FEE;
|
return temBAD_FEE;
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ namespace ripple {
|
|||||||
TER
|
TER
|
||||||
CreateOffer::preflight (PreflightContext const& ctx)
|
CreateOffer::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto& tx = ctx.tx;
|
auto& tx = ctx.tx;
|
||||||
auto& j = ctx.j;
|
auto& j = ctx.j;
|
||||||
|
|
||||||
@@ -123,7 +127,7 @@ CreateOffer::preflight (PreflightContext const& ctx)
|
|||||||
return temBAD_ISSUER;
|
return temBAD_ISSUER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ CreateTicket::preflight (PreflightContext const& ctx)
|
|||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (ctx.tx.isFieldPresent (sfExpiration))
|
if (ctx.tx.isFieldPresent (sfExpiration))
|
||||||
{
|
{
|
||||||
if (ctx.tx.getFieldU32 (sfExpiration) == 0)
|
if (ctx.tx.getFieldU32 (sfExpiration) == 0)
|
||||||
@@ -43,7 +47,7 @@ CreateTicket::preflight (PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount
|
STAmount
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ allowDeliverMin (ApplyView const& view)
|
|||||||
TER
|
TER
|
||||||
Payment::preflight (PreflightContext const& ctx)
|
Payment::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto& tx = ctx.tx;
|
auto& tx = ctx.tx;
|
||||||
auto& j = ctx.j;
|
auto& j = ctx.j;
|
||||||
|
|
||||||
@@ -187,7 +191,7 @@ Payment::preflight (PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ namespace ripple {
|
|||||||
TER
|
TER
|
||||||
SetAccount::preflight (PreflightContext const& ctx)
|
SetAccount::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto& tx = ctx.tx;
|
auto& tx = ctx.tx;
|
||||||
auto& j = ctx.j;
|
auto& j = ctx.j;
|
||||||
|
|
||||||
@@ -99,7 +103,7 @@ SetAccount::preflight (PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -44,6 +44,10 @@ SetRegularKey::calculateBaseFee ()
|
|||||||
TER
|
TER
|
||||||
SetRegularKey::preflight (PreflightContext const& ctx)
|
SetRegularKey::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
std::uint32_t const uTxFlags = ctx.tx.getFlags ();
|
std::uint32_t const uTxFlags = ctx.tx.getFlags ();
|
||||||
|
|
||||||
if (uTxFlags & tfUniversalMask)
|
if (uTxFlags & tfUniversalMask)
|
||||||
@@ -54,7 +58,7 @@ SetRegularKey::preflight (PreflightContext const& ctx)
|
|||||||
return temINVALID_FLAG;
|
return temINVALID_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ SetSignerList::preflight (PreflightContext const& ctx)
|
|||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto const result = determineOperation(ctx.tx, ctx.flags, ctx.j);
|
auto const result = determineOperation(ctx.tx, ctx.flags, ctx.j);
|
||||||
if (std::get<0>(result) != tesSUCCESS)
|
if (std::get<0>(result) != tesSUCCESS)
|
||||||
return std::get<0>(result);
|
return std::get<0>(result);
|
||||||
@@ -105,7 +109,7 @@ SetSignerList::preflight (PreflightContext const& ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ namespace ripple {
|
|||||||
TER
|
TER
|
||||||
SetTrust::preflight (PreflightContext const& ctx)
|
SetTrust::preflight (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
auto& tx = ctx.tx;
|
auto& tx = ctx.tx;
|
||||||
auto& j = ctx.j;
|
auto& j = ctx.j;
|
||||||
|
|
||||||
@@ -79,7 +83,7 @@ SetTrust::preflight (PreflightContext const& ctx)
|
|||||||
return temDST_NEEDED;
|
return temDST_NEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -136,6 +136,10 @@ SusPayCreate::preflight (PreflightContext const& ctx)
|
|||||||
ctx.config.features))
|
ctx.config.features))
|
||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
|
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (! isXRP(ctx.tx[sfAmount]))
|
if (! isXRP(ctx.tx[sfAmount]))
|
||||||
return temBAD_AMOUNT;
|
return temBAD_AMOUNT;
|
||||||
|
|
||||||
@@ -150,7 +154,7 @@ SusPayCreate::preflight (PreflightContext const& ctx)
|
|||||||
ctx.tx[sfCancelAfter] <= ctx.tx[sfFinishAfter])
|
ctx.tx[sfCancelAfter] <= ctx.tx[sfFinishAfter])
|
||||||
return temBAD_EXPIRATION;
|
return temBAD_EXPIRATION;
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
@@ -253,6 +257,10 @@ SusPayFinish::preflight (PreflightContext const& ctx)
|
|||||||
ctx.config.features))
|
ctx.config.features))
|
||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
|
|
||||||
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (ctx.tx[~sfMethod])
|
if (ctx.tx[~sfMethod])
|
||||||
{
|
{
|
||||||
// Condition
|
// Condition
|
||||||
@@ -291,7 +299,7 @@ SusPayFinish::preflight (PreflightContext const& ctx)
|
|||||||
return temMALFORMED;
|
return temMALFORMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
@@ -362,7 +370,11 @@ SusPayCancel::preflight (PreflightContext const& ctx)
|
|||||||
ctx.config.features))
|
ctx.config.features))
|
||||||
return temDISABLED;
|
return temDISABLED;
|
||||||
|
|
||||||
return Transactor::preflight(ctx);
|
auto const ret = preflight1 (ctx);
|
||||||
|
if (!isTesSuccess (ret))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return preflight2 (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
|
|||||||
@@ -30,30 +30,42 @@
|
|||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
|
|
||||||
|
/** Performs early sanity checks on the account and fee fields */
|
||||||
TER
|
TER
|
||||||
Transactor::preflight (PreflightContext const& ctx)
|
preflight1 (PreflightContext const& ctx)
|
||||||
{
|
{
|
||||||
auto& tx = ctx.tx;
|
auto const id = ctx.tx.getAccountID(sfAccount);
|
||||||
auto& j = ctx.j;
|
|
||||||
|
|
||||||
auto const id = tx.getAccountID(sfAccount);
|
|
||||||
if (id == zero)
|
if (id == zero)
|
||||||
{
|
{
|
||||||
JLOG(j.warning) << "Transactor::preflight: bad account id";
|
JLOG(ctx.j.warning) << "preflight1: bad account id";
|
||||||
return temBAD_SRC_ACCOUNT;
|
return temBAD_SRC_ACCOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
JLOG(ctx.j.debug) << "preflight1: invalid fee";
|
||||||
|
return temBAD_FEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tesSUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks whether the signature appears valid */
|
||||||
|
TER
|
||||||
|
preflight2 (PreflightContext const& ctx)
|
||||||
|
{
|
||||||
// Extract signing key
|
// Extract signing key
|
||||||
// Transactions contain a signing key. This allows us to trivially verify a
|
// Transactions contain a signing key. This allows us to trivially verify a
|
||||||
// transaction has at least been properly signed without going to disk.
|
// transaction has at least been properly signed without going to disk.
|
||||||
// Each transaction also notes a source account id. This is used to verify
|
// Each transaction also notes a source account id. This is used to verify
|
||||||
// that the signing key is associated with the account.
|
// that the signing key is associated with the account.
|
||||||
// XXX This could be a lot cleaner to prevent unnecessary copying.
|
// XXX This could be a lot cleaner to prevent unnecessary copying.
|
||||||
auto const pk =
|
auto const pk = RippleAddress::createAccountPublic(
|
||||||
RippleAddress::createAccountPublic(
|
ctx.tx.getSigningPubKey());
|
||||||
tx.getSigningPubKey());
|
|
||||||
|
|
||||||
if(! ctx.verify(tx,
|
if(! ctx.verify(ctx.tx,
|
||||||
[&, ctx] (STTx const& tx)
|
[&, ctx] (STTx const& tx)
|
||||||
{
|
{
|
||||||
return (ctx.flags & tapNO_CHECK_SIGN) ||
|
return (ctx.flags & tapNO_CHECK_SIGN) ||
|
||||||
@@ -66,7 +78,7 @@ Transactor::preflight (PreflightContext const& ctx)
|
|||||||
);
|
);
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
JLOG(j.debug) << "apply: Invalid transaction (bad signature)";
|
JLOG(ctx.j.debug) << "preflight2: bad signature";
|
||||||
return temINVALID;
|
return temINVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,12 +214,6 @@ void Transactor::preCompute ()
|
|||||||
|
|
||||||
TER Transactor::apply ()
|
TER Transactor::apply ()
|
||||||
{
|
{
|
||||||
// No point in going any further if the transaction fee is malformed.
|
|
||||||
STAmount const saTxnFee = tx().getTransactionFee ();
|
|
||||||
|
|
||||||
if (!saTxnFee.native () || saTxnFee.negative () || !isLegalNet (saTxnFee))
|
|
||||||
return temBAD_FEE;
|
|
||||||
|
|
||||||
preCompute();
|
preCompute();
|
||||||
|
|
||||||
// Find source account
|
// Find source account
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ public:
|
|||||||
return ctx_.tx;
|
return ctx_.tx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
TER
|
|
||||||
preflight (PreflightContext const& ctx);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TER
|
TER
|
||||||
apply();
|
apply();
|
||||||
@@ -124,6 +120,14 @@ private:
|
|||||||
TER checkMultiSign ();
|
TER checkMultiSign ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Performs early sanity checks on the account and fee fields */
|
||||||
|
TER
|
||||||
|
preflight1 (PreflightContext const& ctx);
|
||||||
|
|
||||||
|
/** Checks whether the signature appears valid */
|
||||||
|
TER
|
||||||
|
preflight2 (PreflightContext const& ctx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user