Compare commits

..

17 Commits

Author SHA1 Message Date
Mayukha Vadari
3e07a64339 Merge branch 'develop' into mvadari/fix-bad-cast 2025-11-18 13:57:57 +05:30
Bart
3fb6acd29e ci: Fix filtering out of Clang 20+ on ARM (#6046)
This change fixes the strategy matrix check to filter out the Clang 20+ on ARM, which still fail due to problems with Boost.
2025-11-17 21:54:13 +00:00
Bart
77b7cef5a7 ci: Use new Debian Trixie images (#6034)
This change uses the new Debian Trixie CI images added by XRPLF/ci#83.
2025-11-17 19:31:19 +00:00
Jingchen
2c187461cc refactor: Retire NegativeUNL amendment (#6033)
Amendments activated for more than 2 years can be retired. This change retires the NegativeUNL amendment.
2025-11-17 14:02:10 +00:00
Mayukha Vadari
c326a80abd re-remove debug lines 2025-11-17 18:16:14 +05:30
Mayukha Vadari
efa2a1b4e7 simplify tests 2025-11-17 18:13:13 +05:30
Mayukha Vadari
8852594a7b fix test 2025-11-17 18:13:03 +05:30
Mayukha Vadari
711d765a80 clean up book_offers 2025-11-17 18:05:01 +05:30
Mayukha Vadari
400cd02325 remove debug lines 2025-11-17 18:01:51 +05:30
Mayukha Vadari
2116ea6eae fix tx_history 2025-11-17 18:01:26 +05:30
Mayukha Vadari
f1f2cc70ab fix get_counts 2025-11-17 17:59:50 +05:30
Mayukha Vadari
9e23d50339 fix connect 2025-11-17 17:58:57 +05:30
Mayukha Vadari
fb5d878b86 fix can_delete 2025-11-17 17:58:22 +05:30
Mayukha Vadari
403bfaa636 fix account_tx 2025-11-17 17:48:20 +05:30
Mayukha Vadari
9fb088cb42 remove debug statements 2025-11-17 17:47:20 +05:30
Mayukha Vadari
e66cfab251 fix tests, more cleanup 2025-11-17 17:20:13 +05:30
Mayukha Vadari
17e4d38dde Fix index for iLimit in RPCCall.cpp 2025-11-17 16:11:35 +05:30
21 changed files with 315 additions and 688 deletions

View File

@@ -130,8 +130,8 @@ def generate_strategy_matrix(all: bool, config: Config) -> list:
if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64':
continue
# We skip all clang-20 on arm64 due to boost 1.86 build error
if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-20' and architecture['platform'] == 'linux/arm64':
# We skip all clang 20+ on arm64 due to Boost build error.
if f'{os['compiler_name']}-{os['compiler_version']}' in ['clang-20', 'clang-21'] and architecture['platform'] == 'linux/arm64':
continue
# Enable code coverage for Debian Bookworm using GCC 15 in Debug and no

View File

@@ -15,63 +15,91 @@
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "12",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "13",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "gcc",
"compiler_version": "15",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "16",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "17",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "18",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "19",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "bookworm",
"compiler_name": "clang",
"compiler_version": "20",
"image_sha": "e1782cd"
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "gcc",
"compiler_version": "14",
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "gcc",
"compiler_version": "15",
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "clang",
"compiler_version": "20",
"image_sha": "0525eae"
},
{
"distro_name": "debian",
"distro_version": "trixie",
"compiler_name": "clang",
"compiler_version": "21",
"image_sha": "0525eae"
},
{
"distro_name": "rhel",

View File

@@ -13,28 +13,12 @@ class Number;
std::string
to_string(Number const& amount);
template <class T1, class T2>
concept ArithmeticWithNumber =
std::is_arithmetic_v<std::remove_reference_t<T1>> &&
std::is_convertible_v<T2, Number>;
template <class T1, class T2>
concept OneNumberParam =
ArithmeticWithNumber<T1, T2> || ArithmeticWithNumber<T2, T1>;
class Number
{
using rep = std::int64_t;
rep mantissa_{0};
int exponent_{std::numeric_limits<int>::lowest()};
using urep = std::make_unsigned_t<rep>;
template <class T>
rep
utoi(T mantissa)
requires std::is_unsigned_v<T>;
public:
// The range for the mantissa when normalized
constexpr static std::int64_t minMantissa = 1'000'000'000'000'000LL;
@@ -51,10 +35,7 @@ public:
explicit constexpr Number() = default;
template <class T>
explicit Number(T mantissa)
requires std::is_unsigned_v<T>;
explicit Number(rep mantissa);
Number(rep mantissa);
explicit Number(rep mantissa, int exponent);
explicit constexpr Number(rep mantissa, int exponent, unchecked) noexcept;
@@ -78,39 +59,13 @@ public:
Number&
operator+=(Number const& x);
template <class T>
Number&
operator+=(T x)
{
return operator+=(Number(x));
}
Number&
operator-=(Number const& x);
template <class T>
Number&
operator-=(T x)
{
return operator-=(Number(x));
}
Number&
operator*=(Number const& x);
template <class T>
Number&
operator*=(T x)
{
return operator*=(Number(x));
}
Number&
operator/=(Number const& x);
template <class T>
Number&
operator/=(T x)
{
return operator/=(Number(x));
}
static constexpr Number
min() noexcept;
@@ -132,26 +87,12 @@ public:
{
return x.mantissa_ == y.mantissa_ && x.exponent_ == y.exponent_;
}
template <class T1, class T2>
friend constexpr bool
operator==(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator==(Number(x), Number(y));
}
friend constexpr bool
operator!=(Number const& x, Number const& y) noexcept
{
return !(x == y);
}
template <class T1, class T2>
friend constexpr bool
operator!=(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator!=(Number(x), Number(y));
}
friend constexpr bool
operator<(Number const& x, Number const& y) noexcept
@@ -182,13 +123,6 @@ public:
// If equal exponents, compare mantissas
return x.mantissa_ < y.mantissa_;
}
template <class T1, class T2>
friend constexpr bool
operator<(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator<(Number(x), Number(y));
}
/** Return the sign of the amount */
constexpr int
@@ -220,39 +154,18 @@ public:
{
return y < x;
}
template <class T1, class T2>
friend constexpr bool
operator>(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator>(Number(x), Number(y));
}
friend constexpr bool
operator<=(Number const& x, Number const& y) noexcept
{
return !(y < x);
}
template <class T1, class T2>
friend constexpr bool
operator<=(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator<=(Number(x), Number(y));
}
friend constexpr bool
operator>=(Number const& x, Number const& y) noexcept
{
return !(x < y);
}
template <class T1, class T2>
friend constexpr bool
operator>=(T1&& x, T2&& y) noexcept
requires OneNumberParam<T1, T2>
{
return operator>=(Number(x), Number(y));
}
friend std::ostream&
operator<<(std::ostream& os, Number const& x)
@@ -279,16 +192,6 @@ private:
class Guard;
};
template <class T>
Number::rep
Number::utoi(T mantissa)
requires std::is_unsigned_v<T>
{
if (mantissa > std::numeric_limits<rep>::max())
throw std::overflow_error("too high");
return static_cast<rep>(mantissa);
}
inline constexpr Number::Number(rep mantissa, int exponent, unchecked) noexcept
: mantissa_{mantissa}, exponent_{exponent}
{
@@ -304,13 +207,6 @@ inline Number::Number(rep mantissa) : Number{mantissa, 0}
{
}
template <class T>
Number::Number(T mantissa)
requires std::is_unsigned_v<T>
: Number{utoi(mantissa), 0}
{
}
inline constexpr Number::rep
Number::mantissa() const noexcept
{
@@ -381,14 +277,6 @@ operator+(Number const& x, Number const& y)
return z;
}
template <class T1, class T2>
constexpr Number
operator+(T1&& x, T2&& y)
requires OneNumberParam<T1, T2>
{
return operator+(Number(x), Number(y));
}
inline Number
operator-(Number const& x, Number const& y)
{
@@ -397,14 +285,6 @@ operator-(Number const& x, Number const& y)
return z;
}
template <class T1, class T2>
constexpr Number
operator-(T1&& x, T2&& y)
requires OneNumberParam<T1, T2>
{
return operator-(Number(x), Number(y));
}
inline Number
operator*(Number const& x, Number const& y)
{
@@ -413,14 +293,6 @@ operator*(Number const& x, Number const& y)
return z;
}
template <class T1, class T2>
constexpr Number
operator*(T1&& x, T2&& y)
requires OneNumberParam<T1, T2>
{
return operator*(Number(x), Number(y));
}
inline Number
operator/(Number const& x, Number const& y)
{
@@ -429,14 +301,6 @@ operator/(Number const& x, Number const& y)
return z;
}
template <class T1, class T2>
constexpr Number
operator/(T1&& x, T2&& y)
requires OneNumberParam<T1, T2>
{
return operator/(Number(x), Number(y));
}
inline constexpr Number
Number::min() noexcept
{

View File

@@ -29,9 +29,7 @@ struct Fees
XRPAmount
accountReserve(std::size_t ownerCount) const
{
auto const p = ownerCount * increment;
auto const s = reserve + p;
return s;
return reserve + ownerCount * increment;
}
};

View File

@@ -42,7 +42,7 @@ public:
IOUAmount() = default;
explicit IOUAmount(Number const& other);
IOUAmount(beast::Zero);
IOUAmount(std::int64_t mantissa, int exponent = 0);
IOUAmount(std::int64_t mantissa, int exponent);
IOUAmount& operator=(beast::Zero);

View File

@@ -64,7 +64,7 @@ public:
operator Number() const noexcept
{
return Number{value()};
return value();
}
/** Return the sign of the amount */

View File

@@ -20,9 +20,7 @@ namespace ripple {
class XRPAmount : private boost::totally_ordered<XRPAmount>,
private boost::additive<XRPAmount>,
private boost::equality_comparable<XRPAmount, std::int64_t>,
private boost::equality_comparable<XRPAmount, int>,
private boost::additive<XRPAmount, std::int64_t>,
private boost::additive<XRPAmount, int>
private boost::additive<XRPAmount, std::int64_t>
{
public:
using unit_type = unit::dropTag;
@@ -70,13 +68,11 @@ public:
return XRPAmount{drops_ * rhs};
}
template <class T>
friend constexpr XRPAmount
operator*(T lhs, XRPAmount const& rhs)
requires std::is_convertible_v<T, value_type>
operator*(value_type lhs, XRPAmount const& rhs)
{
// multiplication is commutative
return rhs.operator*(lhs);
return rhs * lhs;
}
XRPAmount&
@@ -131,12 +127,6 @@ public:
{
return drops_ == other;
}
friend bool
operator==(value_type lhs, XRPAmount const& rhs)
{
// multiplication is commutative
return rhs.operator==(lhs);
}
bool
operator<(XRPAmount const& other) const
@@ -153,7 +143,7 @@ public:
operator Number() const noexcept
{
return Number{drops()};
return drops();
}
/** Return the sign of the amount */

View File

@@ -66,7 +66,6 @@ XRPL_FEATURE(XRPFees, Supported::yes, VoteBehavior::DefaultNo
XRPL_FEATURE(DisallowIncoming, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FIX (RemoveNFTokenAutoTrustLine, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(FlowSortStrands, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(NegativeUNL, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(RequireFullyCanonicalSig, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(DeletableAccounts, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(Checks, Supported::yes, VoteBehavior::DefaultYes)
@@ -130,6 +129,7 @@ XRPL_RETIRE_FEATURE(HardenedValidations)
XRPL_RETIRE_FEATURE(ImmediateOfferKilled)
XRPL_RETIRE_FEATURE(MultiSign)
XRPL_RETIRE_FEATURE(MultiSignReserve)
XRPL_RETIRE_FEATURE(NegativeUNL)
XRPL_RETIRE_FEATURE(NonFungibleTokensV1_1)
XRPL_RETIRE_FEATURE(PayChan)
XRPL_RETIRE_FEATURE(SortedDirectories)

View File

@@ -2884,7 +2884,7 @@ assetsToSharesDeposit(
Number(assets.mantissa(), assets.exponent() + vault->at(sfScale))
.truncate()};
Number const shareTotal = Number{issuance->at(sfOutstandingAmount)};
Number const shareTotal = issuance->at(sfOutstandingAmount);
shares = ((shareTotal * assets) / assetTotal).truncate();
return shares;
}
@@ -2913,7 +2913,7 @@ sharesToAssetsDeposit(
shares.exponent() - vault->at(sfScale),
false};
Number const shareTotal{issuance->at(sfOutstandingAmount)};
Number const shareTotal = issuance->at(sfOutstandingAmount);
assets = (assetTotal * shares) / shareTotal;
return assets;
}
@@ -2939,7 +2939,7 @@ assetsToSharesWithdraw(
STAmount shares{vault->at(sfShareMPTID)};
if (assetTotal == 0)
return shares;
Number const shareTotal{issuance->at(sfOutstandingAmount)};
Number const shareTotal = issuance->at(sfOutstandingAmount);
Number result = (shareTotal * assets) / assetTotal;
if (truncate == TruncateShares::yes)
result = result.truncate();
@@ -2967,7 +2967,7 @@ sharesToAssetsWithdraw(
STAmount assets{vault->at(sfAsset)};
if (assetTotal == 0)
return assets;
Number const shareTotal{issuance->at(sfOutstandingAmount)};
Number const shareTotal = issuance->at(sfOutstandingAmount);
assets = (assetTotal * shares) / shareTotal;
return assets;
}

View File

@@ -16,12 +16,6 @@ QualityFunction::QualityFunction(
{
if (quality.rate() <= beast::zero)
Throw<std::runtime_error>("QualityFunction quality rate is 0.");
static_assert(std::is_arithmetic_v<std::remove_reference_t<int>>);
static_assert(std::is_convertible_v<ripple::STAmount, Number>);
static_assert(ripple::OneNumberParam<int, ripple::STAmount>);
static_assert(!ripple::OneNumberParam<Number, Number>);
b_ = 1 / quality.rate();
}

View File

@@ -15,7 +15,6 @@ namespace test {
/*
* This file implements the following negative UNL related tests:
* -- test filling and applying ttUNL_MODIFY Tx and ledger update
* -- test ttUNL_MODIFY Tx failure without featureNegativeUNL amendment
* -- test the NegativeUNLVote class. The test cases are split to multiple
* test classes to allow parallel execution.
* -- test the negativeUNLFilter function
@@ -208,7 +207,7 @@ class NegativeUNL_test : public beast::unit_test::suite
testcase("Create UNLModify Tx and apply to ledgers");
jtx::Env env(*this, jtx::testable_amendments() | featureNegativeUNL);
jtx::Env env(*this, jtx::testable_amendments());
std::vector<PublicKey> publicKeys = createPublicKeys(3);
// genesis ledger
auto l = std::make_shared<Ledger>(
@@ -216,7 +215,6 @@ class NegativeUNL_test : public beast::unit_test::suite
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
BEAST_EXPECT(l->rules().enabled(featureNegativeUNL));
// Record the public keys and ledger sequences of expected negative UNL
// validators when we build the ledger history
@@ -500,44 +498,6 @@ class NegativeUNL_test : public beast::unit_test::suite
}
};
class NegativeUNLNoAmendment_test : public beast::unit_test::suite
{
void
testNegativeUNLNoAmendment()
{
testcase("No negative UNL amendment");
jtx::Env env(*this, jtx::testable_amendments() - featureNegativeUNL);
std::vector<PublicKey> publicKeys = createPublicKeys(1);
// genesis ledger
auto l = std::make_shared<Ledger>(
create_genesis,
env.app().config(),
std::vector<uint256>{},
env.app().getNodeFamily());
BEAST_EXPECT(!l->rules().enabled(featureNegativeUNL));
// generate more ledgers
for (auto i = 0; i < 256 - 1; ++i)
{
l = std::make_shared<Ledger>(
*l, env.app().timeKeeper().closeTime());
}
BEAST_EXPECT(l->seq() == 256);
auto txDisable_0 = createTx(true, l->seq(), publicKeys[0]);
OpenView accum(&*l);
BEAST_EXPECT(applyAndTestResult(env, accum, txDisable_0, false));
accum.apply(*l);
BEAST_EXPECT(negUnlSizeTest(l, 0, false, false));
}
void
run() override
{
testNegativeUNLNoAmendment();
}
};
/**
* Utility class for creating validators and ledger history
*/
@@ -563,7 +523,7 @@ struct NetworkHistory
};
NetworkHistory(beast::unit_test::suite& suite, Parameter const& p)
: env(suite, jtx::testable_amendments() | featureNegativeUNL)
: env(suite, jtx::testable_amendments())
, param(p)
, validations(env.app().getValidations())
{
@@ -1867,7 +1827,6 @@ class NegativeUNLVoteFilterValidations_test : public beast::unit_test::suite
};
BEAST_DEFINE_TESTSUITE(NegativeUNL, consensus, ripple);
BEAST_DEFINE_TESTSUITE(NegativeUNLNoAmendment, consensus, ripple);
BEAST_DEFINE_TESTSUITE(NegativeUNLVoteInternal, consensus, ripple);
BEAST_DEFINE_TESTSUITE_MANUAL(NegativeUNLVoteScoreTable, consensus, ripple);

View File

@@ -142,34 +142,6 @@ public:
}
};
/*
template <class T1, class T2>
concept STAmountParams =
std::is_convertible_v<T1, STAmount> && std::is_convertible_v<T2, STAmount>;
template <class T1, class T2>
STAmount
operator-(T2&& lhs, T1&& rhs)
requires STAmountParams<T1, T2>
{
return STAmount(lhs) - STAmount(rhs);
}
*/
/*
STAmount
operator-(PrettyAmount&& lhs, STAmount const& rhs)
{
return STAmount(lhs) - rhs;
}
STAmount
operator-(STAmount const& lhs, PrettyAmount&& rhs)
{
return lhs - STAmount(rhs);
}
*/
inline bool
operator==(PrettyAmount const& lhs, PrettyAmount const& rhs)
{

View File

@@ -370,7 +370,6 @@ public:
env(pay(alice, bob, USD(1)), sendmax(USD(10)));
env.close();
auto const ten = USD(10);
env.require(balance(alice, USD(10) - amountWithRate));
env.require(balance(bob, USD(1)));
}

View File

@@ -124,7 +124,8 @@ class Feature_test : public beast::unit_test::suite
featureToName(fixRemoveNFTokenAutoTrustLine) ==
"fixRemoveNFTokenAutoTrustLine");
BEAST_EXPECT(featureToName(featureFlow) == "Flow");
BEAST_EXPECT(featureToName(featureNegativeUNL) == "NegativeUNL");
BEAST_EXPECT(
featureToName(featureDeletableAccounts) == "DeletableAccounts");
BEAST_EXPECT(
featureToName(fixIncludeKeyletFields) == "fixIncludeKeyletFields");
BEAST_EXPECT(featureToName(featureTokenEscrow) == "TokenEscrow");

File diff suppressed because it is too large Load Diff

View File

@@ -731,7 +731,6 @@ class Simulate_test : public beast::unit_test::suite
{
auto validateOutput = [&](Json::Value const& resp,
Json::Value const& tx) {
static_assert(ArithmeticWithNumber<XRPAmount, int>);
auto result = resp[jss::result];
checkBasicReturnValidity(
result,

View File

@@ -346,9 +346,7 @@ RCLConsensus::Adaptor::onClose(
prevLedger, validations, initialSet, j_);
}
}
else if (
prevLedger->isVotingLedger() &&
prevLedger->rules().enabled(featureNegativeUNL))
else if (prevLedger->isVotingLedger())
{
// previous ledger was a voting ledger,
// so the current consensus session is for a flag ledger,
@@ -1015,8 +1013,7 @@ RCLConsensus::Adaptor::preStartRound(
inboundTransactions_.newRound(prevLgr.seq());
// Notify NegativeUNLVote that new validators are added
if (prevLgr.ledger_->rules().enabled(featureNegativeUNL) &&
!nowTrusted.empty())
if (!nowTrusted.empty())
nUnlVote_.newValidators(prevLgr.seq() + 1, nowTrusted);
// propose only if we're in sync with the network (and validating)

View File

@@ -28,7 +28,7 @@ buildLedgerImpl(
{
auto built = std::make_shared<Ledger>(*parent, closeTime);
if (built->isFlagLedger() && built->rules().enabled(featureNegativeUNL))
if (built->isFlagLedger())
{
built->updateNegativeUNL();
}

View File

@@ -2063,8 +2063,7 @@ NetworkOPsImp::beginConsensus(
"ripple::NetworkOPsImp::beginConsensus : closedLedger parent matches "
"hash");
if (prevLedger->rules().enabled(featureNegativeUNL))
app_.validators().setNegativeUNL(prevLedger->negativeUNL());
app_.validators().setNegativeUNL(prevLedger->negativeUNL());
TrustChanges const changes = app_.validators().updateTrusted(
app_.getValidations().getCurrentNodeIDs(),
closingInfo.parentCloseTime,

View File

@@ -51,13 +51,6 @@ Transactor::invokePreflight<Change>(PreflightContext const& ctx)
return temBAD_SEQUENCE;
}
if (ctx.tx.getTxnType() == ttUNL_MODIFY &&
!ctx.rules.enabled(featureNegativeUNL))
{
JLOG(ctx.j.warn()) << "Change: NegativeUNL not enabled";
return temDISABLED;
}
return tesSUCCESS;
}

View File

@@ -135,6 +135,38 @@ private:
}
}
static std::optional<std::int32_t>
jvParseInt(Json::Value const& param)
{
if (param.isUInt() || param.isInt())
return param.asInt();
if (param.isString())
{
std::int32_t v;
if (beast::lexicalCastChecked(v, param.asString()))
return v;
}
return std::nullopt;
}
static std::optional<std::uint32_t>
jvParseUInt(Json::Value const& param)
{
if (param.isUInt() || (param.isInt() && param.asInt() >= 0))
return param.asUInt();
if (param.isString())
{
std::uint32_t v;
if (beast::lexicalCastChecked(v, param.asString()))
return v;
}
return std::nullopt;
}
static bool
validPublicKey(
std::string const& strPk,
@@ -266,24 +298,50 @@ private:
}
else
{
std::int64_t uLedgerMin = jvParams[1u].asInt();
std::int64_t uLedgerMax = jvParams[2u].asInt();
std::int32_t ledgerMin, ledgerMax;
if (auto ledgerMinOpt = jvParseInt(jvParams[1u]))
{
ledgerMin = *ledgerMinOpt;
}
else
{
return rpcError(rpcINVALID_LGR_RANGE);
}
if (uLedgerMax != -1 && uLedgerMax < uLedgerMin)
if (auto ledgerMaxOpt = jvParseInt(jvParams[2u]))
{
ledgerMax = *ledgerMaxOpt;
}
else
{
return rpcError(rpcINVALID_LGR_RANGE);
}
if (ledgerMax != -1 && ledgerMax < ledgerMin)
{
if (apiVersion_ == 1)
return rpcError(rpcLGR_IDXS_INVALID);
return rpcError(rpcNOT_SYNCED);
}
jvRequest[jss::ledger_index_min] = jvParams[1u].asInt();
jvRequest[jss::ledger_index_max] = jvParams[2u].asInt();
jvRequest[jss::ledger_index_min] = ledgerMin;
jvRequest[jss::ledger_index_max] = ledgerMax;
if (iParams >= 4)
jvRequest[jss::limit] = jvParams[3u].asInt();
{
if (auto limit = jvParseInt(jvParams[3u]))
jvRequest[jss::limit] = *limit;
else
return RPC::invalid_field_error(jss::limit);
}
if (iParams >= 5)
jvRequest[jss::offset] = jvParams[4u].asInt();
{
if (auto offset = jvParseInt(jvParams[4u]))
jvRequest[jss::offset] = *offset;
else
return RPC::invalid_field_error(jss::offset);
}
}
return jvRequest;
@@ -332,15 +390,21 @@ private:
if (jvParams.size() >= 5)
{
int iLimit = jvParams[5u].asInt();
if (iLimit > 0)
jvRequest[jss::limit] = iLimit;
if (auto limit = jvParseInt(jvParams[4u]))
{
if (limit > 0)
jvRequest[jss::limit] = *limit;
}
else
return RPC::invalid_field_error(jss::limit);
}
if (jvParams.size() >= 6 && jvParams[5u].asInt())
if (jvParams.size() >= 6)
{
jvRequest[jss::proof] = true;
if (auto proof = jvParseInt(jvParams[5u]))
jvRequest[jss::proof] = true;
else
return RPC::invalid_field_error(jss::proof);
}
if (jvParams.size() == 7)
@@ -360,7 +424,12 @@ private:
std::string input = jvParams[0u].asString();
if (input.find_first_not_of("0123456789") == std::string::npos)
jvRequest["can_delete"] = jvParams[0u].asUInt();
{
if (auto seq = jvParseUInt(jvParams[0u]))
jvRequest["can_delete"] = *seq;
else
return RPC::invalid_field_error(jss::can_delete);
}
else
jvRequest["can_delete"] = input;
@@ -376,7 +445,10 @@ private:
if (jvParams.size() == 2)
{
jvRequest[jss::ip] = ip;
jvRequest[jss::port] = jvParams[1u].asUInt();
if (auto port = jvParseUInt(jvParams[1u]))
jvRequest[jss::port] = *port;
else
return RPC::invalid_field_error(jss::port);
return jvRequest;
}
@@ -385,8 +457,13 @@ private:
{
std::size_t colon = ip.find_last_of(":");
jvRequest[jss::ip] = std::string{ip, 0, colon};
jvRequest[jss::port] =
Json::Value{std::string{ip, colon + 1}}.asUInt();
std::uint32_t port;
if (beast::lexicalCastChecked(port, std::string{ip, colon + 1}))
jvRequest[jss::port] = port;
else
return RPC::invalid_field_error(jss::port);
return jvRequest;
}
@@ -459,7 +536,12 @@ private:
Json::Value jvRequest(Json::objectValue);
if (jvParams.size())
jvRequest[jss::min_count] = jvParams[0u].asUInt();
{
if (auto minCount = jvParseUInt(jvParams[0u]))
jvRequest[jss::min_count] = *minCount;
else
return RPC::invalid_field_error(jss::min_count);
}
return jvRequest;
}
@@ -1071,7 +1153,10 @@ private:
{
Json::Value jvRequest{Json::objectValue};
jvRequest[jss::start] = jvParams[0u].asUInt();
if (auto const start = jvParseUInt(jvParams[0u]))
jvRequest[jss::start] = *start;
else
return RPC::invalid_field_error(jss::start);
return jvRequest;
}