mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
Step 3: Automatically switch precision in the transaction engine
- Default Number outside of transaction processing to be "large" so RPC will work.
This commit is contained in:
@@ -36,9 +36,8 @@ struct make_unsigned<ripple::numberint128>
|
||||
namespace ripple {
|
||||
|
||||
thread_local Number::rounding_mode Number::mode_ = Number::to_nearest;
|
||||
// TODO: Once the Rules switching is implemented, default to largeRange
|
||||
thread_local std::reference_wrapper<MantissaRange const> Number::range_ =
|
||||
smallRange; // largeRange;
|
||||
largeRange;
|
||||
|
||||
Number::rounding_mode
|
||||
Number::getround()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
//
|
||||
#include <xrpl/basics/LocalValue.h>
|
||||
#include <xrpl/basics/Number.h>
|
||||
#include <xrpl/basics/base_uint.h>
|
||||
#include <xrpl/basics/hardened_hash.h>
|
||||
#include <xrpl/beast/hash/uhash.h>
|
||||
#include <xrpl/beast/utility/instrumentation.h>
|
||||
#include <xrpl/protocol/Feature.h>
|
||||
#include <xrpl/protocol/Rules.h>
|
||||
#include <xrpl/protocol/STVector256.h>
|
||||
|
||||
#include <memory>
|
||||
@@ -33,6 +35,15 @@ getCurrentTransactionRules()
|
||||
void
|
||||
setCurrentTransactionRules(std::optional<Rules> r)
|
||||
{
|
||||
// Make global changes associated with the rules before the value is moved.
|
||||
// Push the appropriate setting, instead of having the class pull every time
|
||||
// the value is needed. That could get expensive fast.
|
||||
bool enableLargeNumbers = !r ||
|
||||
(r->enabled(featureSingleAssetVault) /*||
|
||||
r->enabled(featureLendingProtocol)*/);
|
||||
Number::setMantissaScale(
|
||||
enableLargeNumbers ? MantissaRange::large : MantissaRange::small);
|
||||
|
||||
*getCurrentTransactionRulesRef() = std::move(r);
|
||||
}
|
||||
|
||||
|
||||
@@ -1115,6 +1115,10 @@ Transactor::operator()()
|
||||
{
|
||||
JLOG(j_.trace()) << "apply: " << ctx_.tx.getTransactionID();
|
||||
|
||||
// These global updates really should have been for every Transaction
|
||||
// step: preflight, preclaim, and doApply. And even calculateBaseFee. See
|
||||
// with_txn_type().
|
||||
//
|
||||
// raii classes for the current ledger rules.
|
||||
// fixUniversalNumber predate the rulesGuard and should be replaced.
|
||||
NumberSO stNumberSO{view().rules().enabled(fixUniversalNumber)};
|
||||
@@ -1131,7 +1135,7 @@ Transactor::operator()()
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
JLOG(j_.fatal()) << "Transaction serdes mismatch";
|
||||
JLOG(j_.info()) << to_string(ctx_.tx.getJson(JsonOptions::none));
|
||||
JLOG(j_.fatal()) << ctx_.tx.getJson(JsonOptions::none);
|
||||
JLOG(j_.fatal()) << s2.getJson(JsonOptions::none);
|
||||
UNREACHABLE(
|
||||
"ripple::Transactor::operator() : transaction serdes mismatch");
|
||||
|
||||
@@ -34,8 +34,31 @@ struct UnknownTxnType : std::exception
|
||||
// throw an "UnknownTxnType" exception on error
|
||||
template <class F>
|
||||
auto
|
||||
with_txn_type(TxType txnType, F&& f)
|
||||
with_txn_type(Rules const& rules, TxType txnType, F&& f)
|
||||
{
|
||||
// These global updates really should have been for every Transaction
|
||||
// step: preflight, preclaim, calculateBaseFee, and doApply. Unfortunately,
|
||||
// they were only included in doApply (via Transactor::operator()). That may
|
||||
// have been sufficient when the changes were only related to operations
|
||||
// that mutated data, but some features will now change how they read data,
|
||||
// so these need to be more global.
|
||||
//
|
||||
// To prevent unintentional side effects on existing checks, they will be
|
||||
// set for every operation only once SingleAssetVault (or later
|
||||
// LendingProtocol) are enabled.
|
||||
//
|
||||
// See also Transactor::operator().
|
||||
//
|
||||
std::optional<NumberSO> stNumberSO;
|
||||
std::optional<CurrentTransactionRulesGuard> rulesGuard;
|
||||
if (rules.enabled(featureSingleAssetVault) /*|| rules.enabled(featureLendingProtocol)*/)
|
||||
{
|
||||
// raii classes for the current ledger rules.
|
||||
// fixUniversalNumber predate the rulesGuard and should be replaced.
|
||||
stNumberSO.emplace(rules.enabled(fixUniversalNumber));
|
||||
rulesGuard.emplace(rules);
|
||||
}
|
||||
|
||||
switch (txnType)
|
||||
{
|
||||
#pragma push_macro("TRANSACTION")
|
||||
@@ -99,7 +122,7 @@ invoke_preflight(PreflightContext const& ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
return with_txn_type(ctx.tx.getTxnType(), [&]<typename T>() {
|
||||
return with_txn_type(ctx.rules, ctx.tx.getTxnType(), [&]<typename T>() {
|
||||
auto const tec = Transactor::invokePreflight<T>(ctx);
|
||||
return std::make_pair(
|
||||
tec,
|
||||
@@ -126,50 +149,51 @@ invoke_preclaim(PreclaimContext const& ctx)
|
||||
{
|
||||
// use name hiding to accomplish compile-time polymorphism of static
|
||||
// class functions for Transactor and derived classes.
|
||||
return with_txn_type(ctx.tx.getTxnType(), [&]<typename T>() -> TER {
|
||||
// preclaim functionality is divided into two sections:
|
||||
// 1. Up to and including the signature check: returns NotTEC.
|
||||
// All transaction checks before and including checkSign
|
||||
// MUST return NotTEC, or something more restrictive.
|
||||
// Allowing tec results in these steps risks theft or
|
||||
// destruction of funds, as a fee will be charged before the
|
||||
// signature is checked.
|
||||
// 2. After the signature check: returns TER.
|
||||
return with_txn_type(
|
||||
ctx.view.rules(), ctx.tx.getTxnType(), [&]<typename T>() -> TER {
|
||||
// preclaim functionality is divided into two sections:
|
||||
// 1. Up to and including the signature check: returns NotTEC.
|
||||
// All transaction checks before and including checkSign
|
||||
// MUST return NotTEC, or something more restrictive.
|
||||
// Allowing tec results in these steps risks theft or
|
||||
// destruction of funds, as a fee will be charged before the
|
||||
// signature is checked.
|
||||
// 2. After the signature check: returns TER.
|
||||
|
||||
// If the transactor requires a valid account and the
|
||||
// transaction doesn't list one, preflight will have already
|
||||
// a flagged a failure.
|
||||
auto const id = ctx.tx.getAccountID(sfAccount);
|
||||
// If the transactor requires a valid account and the
|
||||
// transaction doesn't list one, preflight will have already
|
||||
// a flagged a failure.
|
||||
auto const id = ctx.tx.getAccountID(sfAccount);
|
||||
|
||||
if (id != beast::zero)
|
||||
{
|
||||
if (NotTEC const preSigResult = [&]() -> NotTEC {
|
||||
if (NotTEC const result =
|
||||
T::checkSeqProxy(ctx.view, ctx.tx, ctx.j))
|
||||
return result;
|
||||
if (id != beast::zero)
|
||||
{
|
||||
if (NotTEC const preSigResult = [&]() -> NotTEC {
|
||||
if (NotTEC const result =
|
||||
T::checkSeqProxy(ctx.view, ctx.tx, ctx.j))
|
||||
return result;
|
||||
|
||||
if (NotTEC const result =
|
||||
T::checkPriorTxAndLastLedger(ctx))
|
||||
return result;
|
||||
if (NotTEC const result =
|
||||
T::checkPriorTxAndLastLedger(ctx))
|
||||
return result;
|
||||
|
||||
if (NotTEC const result =
|
||||
T::checkPermission(ctx.view, ctx.tx))
|
||||
return result;
|
||||
if (NotTEC const result =
|
||||
T::checkPermission(ctx.view, ctx.tx))
|
||||
return result;
|
||||
|
||||
if (NotTEC const result = T::checkSign(ctx))
|
||||
return result;
|
||||
if (NotTEC const result = T::checkSign(ctx))
|
||||
return result;
|
||||
|
||||
return tesSUCCESS;
|
||||
}())
|
||||
return preSigResult;
|
||||
return tesSUCCESS;
|
||||
}())
|
||||
return preSigResult;
|
||||
|
||||
if (TER const result =
|
||||
T::checkFee(ctx, calculateBaseFee(ctx.view, ctx.tx)))
|
||||
return result;
|
||||
}
|
||||
if (TER const result = T::checkFee(
|
||||
ctx, calculateBaseFee(ctx.view, ctx.tx)))
|
||||
return result;
|
||||
}
|
||||
|
||||
return T::preclaim(ctx);
|
||||
});
|
||||
return T::preclaim(ctx);
|
||||
});
|
||||
}
|
||||
catch (UnknownTxnType const& e)
|
||||
{
|
||||
@@ -204,7 +228,7 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx)
|
||||
{
|
||||
try
|
||||
{
|
||||
return with_txn_type(tx.getTxnType(), [&]<typename T>() {
|
||||
return with_txn_type(view.rules(), tx.getTxnType(), [&]<typename T>() {
|
||||
return T::calculateBaseFee(view, tx);
|
||||
});
|
||||
}
|
||||
@@ -264,10 +288,11 @@ invoke_apply(ApplyContext& ctx)
|
||||
{
|
||||
try
|
||||
{
|
||||
return with_txn_type(ctx.tx.getTxnType(), [&]<typename T>() {
|
||||
T p(ctx);
|
||||
return p();
|
||||
});
|
||||
return with_txn_type(
|
||||
ctx.view().rules(), ctx.tx.getTxnType(), [&]<typename T>() {
|
||||
T p(ctx);
|
||||
return p();
|
||||
});
|
||||
}
|
||||
catch (UnknownTxnType const& e)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user