Compare commits

..

4 Commits

Author SHA1 Message Date
Bart
04249ae86e Apply clang-tidy diff 2026-04-28 13:39:39 -04:00
Bart
7962ed3c22 Merge branch 'develop' into bthomee/logic 2026-04-28 13:39:18 -04:00
Bart
58beb2d9ba Remove unused function 2026-04-28 11:16:59 -04:00
Bart
0d6f9b8428 refactor: Revert certain Throws by LogicErrors 2026-04-27 15:49:02 -04:00
4 changed files with 13 additions and 191 deletions

View File

@@ -229,19 +229,6 @@ public:
std::shared_ptr<Serializer const> const& txn,
std::shared_ptr<Serializer const> const& metaData) override;
// Insert the transaction, and return the hash of the SHAMap leaf node
// holding the transaction. The hash can be used to fetch the transaction
// directly, instead of traversing the SHAMap
// @param key transaction ID
// @param txn transaction
// @param metaData transaction metadata
// @return hash of SHAMap leaf node that holds the transaction
uint256
rawTxInsertWithHash(
uint256 const& key,
std::shared_ptr<Serializer const> const& txn,
std::shared_ptr<Serializer const> const& metaData);
//--------------------------------------------------------------------------
void

View File

@@ -222,12 +222,9 @@ Number::Guard::bringIntoRange(
{
mantissa *= 10;
--exponent;
std::cout << "bringIntoRange. mantissa*=10: " << mantissa << ", exponent: " << exponent
<< std::endl;
}
if (exponent < minExponent)
{
std::cout << "bringIntoRange. zero\n";
constexpr Number zero = Number{};
negative = zero.negative_;
@@ -249,50 +246,13 @@ Number::Guard::doRoundUp(
auto r = round();
if (r == 1 || (r == 0 && (mantissa & 1) == 1))
{
std::cout << "doRoundUp. r: " << r << std::endl;
if (isFeatureEnabled(fixCleanup3_2_0) || !getCurrentTransactionRules())
++mantissa;
// Ensure mantissa after incrementing fits within both the
// min/maxMantissa range and is a valid "rep".
if (mantissa > maxMantissa || mantissa > maxRep)
{
// Ensure mantissa after incrementing fits within both the
// min/maxMantissa range and is a valid "rep".
if (mantissa < maxMantissa && mantissa < maxRep)
{
// Nothing unusual here, just increment the mantissa
++mantissa;
std::cout << "\tmantissa++: " << mantissa << std::endl;
}
else
{
// Incrementing the mantissa will require dividing, which will require rounding. So
// _don't_ increment the mantissa. Instead, divide and round recursively. It should
// be impossible to recurse more than once, because once the mantissa is divided by
// 10, it will be _well_ under maxMantissa and maxRep, so adding 1 will have no
// change of bringing it back over.
push(mantissa % 10);
mantissa /= 10;
++exponent;
XRPL_ASSERT_PARTS(
mantissa < maxMantissa && mantissa < maxRep,
"xrpl::Number::Guard::doRoundUp",
"can't recurse more than once");
std::cout << "\tmantissa/=10: " << mantissa << ", exponent: " << exponent
<< std::endl;
// Here be dragons
doRoundUp(negative, mantissa, exponent, minMantissa, maxMantissa, location);
return;
}
}
else
{
// Need to preserve the incorrect behavior until the fix amendment can be retired,
// because otherwise would risk an unplanned ledger fork.
++mantissa;
// Ensure mantissa after incrementing fits within both the
// min/maxMantissa range and is a valid "rep".
if (mantissa > maxMantissa || mantissa > maxRep)
{
mantissa /= 10;
++exponent;
}
mantissa /= 10;
++exponent;
}
}
bringIntoRange(negative, mantissa, exponent, minMantissa);
@@ -707,8 +667,6 @@ Number::operator*=(Number const& y)
auto const& minMantissa = range.min;
auto const& maxMantissa = range.max;
std::cout << "zn: " << zn << ", zm: " << zm << ", ze: " << ze << std::endl;
while (zm > maxMantissa || zm > maxRep)
{
// The following is optimization for:
@@ -717,9 +675,6 @@ Number::operator*=(Number const& y)
g.push(divu10(zm));
++ze;
}
std::cout << "zn: " << zn << ", zm: " << zm << ", ze: " << ze << std::endl;
xm = static_cast<internalrep>(zm);
xe = ze;
g.doRoundUp(
@@ -832,7 +787,8 @@ Number::operator/=(Number const& y)
return *this;
}
Number::operator rep() const
Number::
operator rep() const
{
rep drops = mantissa();
int offset = exponent();

View File

@@ -14,7 +14,6 @@
#include <xrpl/nodestore/NodeObject.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Fees.h>
#include <xrpl/protocol/HashPrefix.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/KeyType.h>
#include <xrpl/protocol/Keylet.h>
@@ -31,7 +30,6 @@
#include <xrpl/protocol/Seed.h>
#include <xrpl/protocol/Serializer.h>
#include <xrpl/protocol/SystemParameters.h>
#include <xrpl/protocol/digest.h>
#include <xrpl/shamap/Family.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapItem.h>
@@ -43,7 +41,6 @@
#include <exception>
#include <memory>
#include <optional>
#include <stdexcept>
#include <utility>
#include <vector>
@@ -493,14 +490,14 @@ void
Ledger::rawErase(std::shared_ptr<SLE> const& sle)
{
if (!stateMap_.delItem(sle->key()))
Throw<std::logic_error>("Ledger::rawErase: key not found");
LogicError("Ledger::rawErase: key not found");
}
void
Ledger::rawErase(uint256 const& key)
{
if (!stateMap_.delItem(key))
Throw<std::logic_error>("Ledger::rawErase: key not found");
LogicError("Ledger::rawErase: key not found");
}
void
@@ -510,7 +507,7 @@ Ledger::rawInsert(std::shared_ptr<SLE> const& sle)
sle->add(ss);
if (!stateMap_.addGiveItem(
SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle->key(), ss.slice())))
Throw<std::logic_error>("Ledger::rawInsert: key already exists");
LogicError("Ledger::rawInsert: key already exists");
}
void
@@ -520,7 +517,7 @@ Ledger::rawReplace(std::shared_ptr<SLE> const& sle)
sle->add(ss);
if (!stateMap_.updateGiveItem(
SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle->key(), ss.slice())))
Throw<std::logic_error>("Ledger::rawReplace: key not found");
LogicError("Ledger::rawReplace: key not found");
}
void
@@ -536,27 +533,7 @@ Ledger::rawTxInsert(
s.addVL(txn->peekData());
s.addVL(metaData->peekData());
if (!txMap_.addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, make_shamapitem(key, s.slice())))
Throw<std::logic_error>("duplicate_tx: " + to_string(key));
}
uint256
Ledger::rawTxInsertWithHash(
uint256 const& key,
std::shared_ptr<Serializer const> const& txn,
std::shared_ptr<Serializer const> const& metaData)
{
XRPL_ASSERT(metaData, "xrpl::Ledger::rawTxInsertWithHash : non-null metadata input");
// low-level - just add to table
Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
s.addVL(txn->peekData());
s.addVL(metaData->peekData());
auto item = make_shamapitem(key, s.slice());
auto hash = sha512Half(HashPrefix::txNode, item->slice(), item->key());
if (!txMap_.addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, std::move(item)))
Throw<std::logic_error>("duplicate_tx: " + to_string(key));
return hash;
LogicError("duplicate_tx: " + to_string(key));
}
bool

View File

@@ -1584,101 +1584,3 @@ public:
BEAST_DEFINE_TESTSUITE(Number, basics, xrpl);
} // namespace xrpl
#include <xrpl/basics/Number.h>
#include <xrpl/beast/unit_test.h>
#include <xrpl/protocol/AccountID.h>
#include <xrpl/protocol/MPTIssue.h>
#include <xrpl/protocol/STAmount.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <cstdint>
#include <limits>
#include <sstream>
#include <string>
namespace xrpl {
class NumberUpwardWrongDirection_test : public beast::unit_test::suite
{
using BigInt = boost::multiprecision::cpp_int;
static std::string
fmt(BigInt const& value)
{
std::ostringstream os;
os << value;
auto s = os.str();
std::string out;
int count = 0;
for (auto it = s.rbegin(); it != s.rend(); ++it)
{
if (count && count % 3 == 0)
out.insert(out.begin(), '_');
out.insert(out.begin(), *it);
++count;
}
return out;
}
public:
void
testUpwardRoundsDown()
{
testcase << "upward rounding produces a value below exact at maxRep cusp";
auto const origScale = Number::getMantissaScale();
auto const origRound = Number::setround(Number::upward);
Number::setMantissaScale(MantissaRange::large);
constexpr std::int64_t aValue = 1'000'000'000'000'049'863LL;
constexpr std::int64_t bValue = 9'223'372'036'854'315'903LL;
// JSON -> STAmount -> Number
AccountID const dummyIssuer = AccountID{42u};
MPTIssue const issue(/*sequence=*/1u, dummyIssuer);
STAmount const amountA{MPTAmount{aValue}, issue};
STAmount const amountB{MPTAmount{bValue}, issue};
// Public conversion operator: STAmount::operator Number() const.
Number const a = amountA;
Number const b = amountB;
Number const product = a * b;
// Exact reference in BigInt.
BigInt const exactProduct = BigInt(aValue) * BigInt(bValue);
// What Number actually stored.
BigInt storedValue = BigInt(product.mantissa());
for (int i = 0; i < product.exponent(); ++i)
storedValue *= 10;
BigInt const signedDifference = storedValue - exactProduct;
log << "\n"
<< " a = " << fmt(BigInt(aValue)) << "\n"
<< " b = " << fmt(BigInt(bValue)) << "\n"
<< " exact a*b = " << fmt(exactProduct) << "\n"
<< " stored = " << fmt(storedValue) << "\n"
<< " stored - exact = " << fmt(signedDifference) << "\n"
<< " upward = " << (signedDifference >= 0 ? "held" : "VIOLATED") << "\n";
BEAST_EXPECT(signedDifference >= 0);
BEAST_EXPECT(product.mantissa() == (std::numeric_limits<std::int64_t>::max() /10) + 1);
BEAST_EXPECT(product.exponent() == 19);
Number::setround(origRound);
Number::setMantissaScale(origScale);
}
void
run() override
{
testUpwardRoundsDown();
}
};
BEAST_DEFINE_TESTSUITE(NumberUpwardWrongDirection, basics, ripple);
} // namespace xrpl