A new MethodNames.h gives every RPC method a string_view constant,
shared by the handler table and the command-line parser table so the
two cannot drift apart. That lets a handler carry its name as a
string_view, and both tables become sorted constexpr arrays found by
binary search, replacing the HandlerTable singleton and its multimap
and RPCParser's runtime table. Their invariants -- a unique name, a
method, and a valid API version range -- are now a static_assert rather
than a logicError on the first request of the process. Handler::Method
becomes a plain function pointer: every method is a free function known
at compile time, so the std::function never captured anything, and
dropping it makes Handler a literal type, which is what a constexpr
table needs; it also makes doCommand's null-method branch dead, since
an empty std::function is no longer representable.
The names being program-lifetime constants removes work throughout.
getHandlerNames and commandLineMethodNames return a span over a
constexpr array instead of building a fresh std::set per call, one of
those on the startup path; PerfLogImp's rpc map keys on string_view, so
it needs neither a transparent hasher nor a string copy per key, and
reports counters through json::StaticString rather than duplicating
each key into the object. Command parameter counts become unsigned with
a named kUnlimitedParams; as ints with -1 for unlimited they were
compared against an unsigned size, so `count < minParams` promoted -1
and was always true, and only the `>= 0` guards kept that from being
reachable.
PerfLog no longer reaches into the RPC layer to learn which methods to
count: makePerfLog takes the names, so xrpld.perflog stops depending on
xrpld.rpc, and PerfLog_test uses five made-up labels, which drops
test.basics > xrpld.rpc as well. Both edges are gone from levelization.
Handler_test's benchmark now asks for kApiMinimumSupportedVersion
instead of a hardcoded 1 and fails if a lookup misses -- once API
versions 1 and 2 retire, getHandler(1, ...) would return at its bounds
check and the benchmark would have silently reported timings for that
check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* upstream/release/3.3.x: (41 commits)
chore: Bump version to 3.3.0
chore: Bump version to 3.3.0-rc7
fix: Increase manifest protocol message size cap and fix manifests relay
fix: Cap untrusted manifests per message and drop oversized ones
chore: Bump version to 3.2.1
chore: Bump version to 3.2.1-rc1
fix: Cap untrusted manifests per message and drop oversized ones
fix: Reject oversized validator manifest before decoding
fix: Reduce untrusted manifest cache cap to 100
fix: Bound untrusted manifest cache
chore: Bump version to 3.3.0-rc6
feat: Package validator-keys inside rippled
chore: Bump version to 3.3.0-rc5
fix: Switch SponsorshipSet to use a delta for sfFeeAmount
fix: Re-revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
chore: Bump version to 3.3.0-rc4
fix: Revert "fix: Set request size limits and differential pricing for get-object-by-hash calls"
chore: Bump version to 3.3.0-rc3
fix: Reduce untrusted manifest cache cap to 100
fix: Revert "fix: Reject oversized SHAMap nodes in gotStaleData and fetch-pack path"
...
* release/3.2.x:
chore: Bump version to 3.2.1
chore: Bump version to 3.2.1-rc1
fix: Cap untrusted manifests per message and drop oversized ones
fix: Reject oversized validator manifest before decoding
fix: Reduce untrusted manifest cache cap to 100
fix: Bound untrusted manifest cache
Bound the number of manifests carried in a single TMManifests message
(kMaxManifestsPerMessage). Trusted manifests are always included and
processed; untrusted gossip is capped per message on both send and
receive, and the sender is charged only when untrusted entries are
actually skipped. Oversized TMManifests messages are dropped without
penalty at the protocol layer so an unpatched peer is not disconnected.
Complements the cache bound from #276/#323.