From bd1b126230ddac9b163c573729799acc5da0c9f1 Mon Sep 17 00:00:00 2001 From: pdp2121 <71317875+pdp2121@users.noreply.github.com> Date: Wed, 22 Apr 2026 16:10:52 -0400 Subject: [PATCH 1/2] feat: Add `--definitions` flag and artifact (#6858) Co-authored-by: Ayaz Salikhov --- .../workflows/reusable-build-test-config.yml | 16 +++++++++ src/test/rpc/ServerDefinitions_test.cpp | 33 ++++++++++++++++++- src/xrpld/app/main/Main.cpp | 24 ++++++++++---- .../server_info/ServerDefinitions.cpp | 17 +++++++++- .../handlers/server_info/ServerDefinitions.h | 10 ++++++ 5 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 src/xrpld/rpc/handlers/server_info/ServerDefinitions.h diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index abbec1ceb4..c2c862d73f 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -210,6 +210,22 @@ jobs: retention-days: 3 if-no-files-found: error + - name: Export server definitions + if: ${{ runner.os != 'Windows' && !inputs.build_only && env.VOIDSTAR_ENABLED != 'true' }} + working-directory: ${{ env.BUILD_DIR }} + run: | + set -o pipefail + ./xrpld --definitions | python3 -m json.tool > server_definitions.json + + - name: Upload server definitions + if: ${{ github.event.repository.visibility == 'public' && inputs.config_name == 'debian-bookworm-gcc-13-amd64-release' }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: server-definitions + path: ${{ env.BUILD_DIR }}/server_definitions.json + retention-days: 3 + if-no-files-found: error + - name: Check linking (Linux) if: ${{ runner.os == 'Linux' && env.SANITIZERS_ENABLED == 'false' }} working-directory: ${{ env.BUILD_DIR }} diff --git a/src/test/rpc/ServerDefinitions_test.cpp b/src/test/rpc/ServerDefinitions_test.cpp index 60312d470d..14567dfd25 100644 --- a/src/test/rpc/ServerDefinitions_test.cpp +++ b/src/test/rpc/ServerDefinitions_test.cpp @@ -1,6 +1,7 @@ - #include +#include + #include #include #include @@ -451,10 +452,40 @@ public: } } + void + testGetServerDefinitionsJson() + { + testcase("getServerDefinitionsJson"); + + auto const& defs = getServerDefinitionsJson(); + for (auto const& field : + {jss::ACCOUNT_SET_FLAGS, + jss::FIELDS, + jss::LEDGER_ENTRY_FLAGS, + jss::LEDGER_ENTRY_FORMATS, + jss::LEDGER_ENTRY_TYPES, + jss::TRANSACTION_FLAGS, + jss::TRANSACTION_FORMATS, + jss::TRANSACTION_RESULTS, + jss::TRANSACTION_TYPES, + jss::TYPES, + jss::hash}) + { + BEAST_EXPECT(defs.isMember(field)); + } + + // verify it returns the same hash as the RPC handler + using namespace test::jtx; + Env env(*this); + auto const rpcResult = env.rpc("server_definitions"); + BEAST_EXPECT(defs[jss::hash] == rpcResult[jss::result][jss::hash]); + } + void run() override { testServerDefinitions(); + testGetServerDefinitionsJson(); } }; diff --git a/src/xrpld/app/main/Main.cpp b/src/xrpld/app/main/Main.cpp index 076faff845..2ee2ac90cd 100644 --- a/src/xrpld/app/main/Main.cpp +++ b/src/xrpld/app/main/Main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -376,12 +378,12 @@ run(int argc, char** argv) "nodeid", po::value(), "Specify the node identity for this server.")( "quorum", po::value(), "Override the minimum validation quorum.")( "silent", "No output to the console after startup.")("standalone,a", "Run with no peers.")( - "verbose,v", "Verbose logging.") - - ("force_ledger_present_range", - po::value(), - "Specify the range of present ledgers for testing purposes. Min and " - "max values are comma separated.")("version", "Display the build version."); + "verbose,v", "Verbose logging.")( + "definitions", "Output server definitions as JSON and exit.")( + "force_ledger_present_range", + po::value(), + "Specify the range of present ledgers for testing purposes. Min and " + "max values are comma separated.")("version", "Display the build version."); po::options_description data("Ledger/Data Options"); data.add_options()("import", importText.c_str())( @@ -503,10 +505,20 @@ run(int argc, char** argv) if (vm.contains("version")) { + // LCOV_EXCL_START std::cout << "xrpld version " << BuildInfo::getVersionString() << std::endl; std::cout << "Git commit hash: " << xrpl::git::getCommitHash() << std::endl; std::cout << "Git build branch: " << xrpl::git::getBuildBranch() << std::endl; return 0; + // LCOV_EXCL_STOP + } + + if (vm.contains("definitions")) + { + // LCOV_EXCL_START + std::cout << Json::FastWriter().write(getServerDefinitionsJson()); + return 0; + // LCOV_EXCL_STOP } #ifndef ENABLE_TESTS diff --git a/src/xrpld/rpc/handlers/server_info/ServerDefinitions.cpp b/src/xrpld/rpc/handlers/server_info/ServerDefinitions.cpp index d3db8cf56d..76f123f442 100644 --- a/src/xrpld/rpc/handlers/server_info/ServerDefinitions.cpp +++ b/src/xrpld/rpc/handlers/server_info/ServerDefinitions.cpp @@ -1,3 +1,5 @@ +#include + #include #include @@ -369,8 +371,21 @@ ServerDefinitions::ServerDefinitions() : defs_{Json::objectValue} } } +ServerDefinitions const& +getDefinitions() +{ + static ServerDefinitions const defs{}; + return defs; +} + } // namespace detail +Json::Value const& +getServerDefinitionsJson() +{ + return detail::getDefinitions().get(); +} + Json::Value doServerDefinitions(RPC::JsonContext& context) { @@ -383,7 +398,7 @@ doServerDefinitions(RPC::JsonContext& context) return RPC::invalid_field_error(jss::hash); } - static detail::ServerDefinitions const defs{}; + auto const& defs = detail::getDefinitions(); if (defs.hashMatches(hash)) { Json::Value jv = Json::objectValue; diff --git a/src/xrpld/rpc/handlers/server_info/ServerDefinitions.h b/src/xrpld/rpc/handlers/server_info/ServerDefinitions.h new file mode 100644 index 0000000000..5b94a2a518 --- /dev/null +++ b/src/xrpld/rpc/handlers/server_info/ServerDefinitions.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace xrpl { + +Json::Value const& +getServerDefinitionsJson(); + +} // namespace xrpl From b41cbb08c643f45025e4b58fd7854d02f4edfd23 Mon Sep 17 00:00:00 2001 From: Alex Kremer Date: Wed, 22 Apr 2026 23:20:14 +0100 Subject: [PATCH 2/2] chore: Add pre-commit hook to fix include style (#6995) Co-authored-by: Ayaz Salikhov --- .pre-commit-config.yaml | 24 ++++++++++++------- bin/pre-commit/fix_include_style.py | 37 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 8 deletions(-) create mode 100755 bin/pre-commit/fix_include_style.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 232e6ca5a3..1c0dc94550 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,6 +20,22 @@ repos: - id: check-merge-conflict args: [--assume-in-merge] + - repo: local + hooks: + - id: clang-tidy + name: "clang-tidy (enable with: TIDY=1)" + entry: ./bin/pre-commit/clang_tidy_check.py + language: python + types_or: [c++, c] + exclude: ^include/xrpl/protocol_autogen + pass_filenames: false # script determines the staged files itself + - id: fix-include-style + name: fix include style + entry: ./bin/pre-commit/fix_include_style.py + language: python + types_or: [c++, c] + exclude: ^include/xrpl/protocol_autogen/(transactions|ledger_entries)/ + - repo: https://github.com/pre-commit/mirrors-clang-format rev: cd481d7b0bfb5c7b3090c21846317f9a8262e891 # frozen: v22.1.0 hooks: @@ -67,14 +83,6 @@ repos: - repo: local hooks: - - id: clang-tidy - name: "clang-tidy (enable with: TIDY=1)" - entry: ./bin/pre-commit/clang_tidy_check.py - language: python - types_or: [c++, c] - exclude: ^include/xrpl/protocol_autogen - pass_filenames: false # script determines the staged files itself - - id: nix-fmt name: Format Nix files entry: | diff --git a/bin/pre-commit/fix_include_style.py b/bin/pre-commit/fix_include_style.py new file mode 100755 index 0000000000..ca59107271 --- /dev/null +++ b/bin/pre-commit/fix_include_style.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +""" +Converts quoted includes (#include "...") to angle-bracket includes +(#include <...>), which is the required style in this project. + +Usage: ./bin/pre-commit/fix_include_style.py ... +""" + +import re +import sys +from pathlib import Path + +PATTERN = re.compile(r'^(\s*#include\s*)"([^"]+)"', re.MULTILINE) + + +def fix_includes(path: Path) -> bool: + original = path.read_text(encoding="utf-8") + fixed = PATTERN.sub(r"\1<\2>", original) + if fixed != original: + path.write_text(fixed, encoding="utf-8") + return False + return True + + +def main() -> int: + files = [Path(f) for f in sys.argv[1:]] + success = True + + for path in files: + success &= fix_includes(path) + + return 0 if success else 1 + + +if __name__ == "__main__": + sys.exit(main())