From bff1aa927f150be377c7cf604ff861cf960fea55 Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S Date: Mon, 7 Apr 2025 15:07:04 -0700 Subject: [PATCH 1/7] Python script to fetch rippled amendments; Github Actions to commit updated cfg file --- .github/workflows/integration_test.yml | 14 +++++ tools/fetch_rippled_amendments.py | 72 ++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 tools/fetch_rippled_amendments.py diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 295b8985d..749097019 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -23,6 +23,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + - name: Load cached .local id: cache-poetry uses: actions/cache@v4 @@ -30,6 +31,19 @@ jobs: path: /home/runner/.local key: dotlocal-${{ env.POETRY_VERSION }} + - name: Fetch latest rippled amendments + if: ${{ github.event_name == 'pull_request' }} + run: | + poetry run python tools/fetch_rippled_amendments.py + + - name: Add and commit rippled.cfg + uses: EndBug/add-and-commit@v9 + with: + message: 'Update rippled.cfg with latest amendments' + committer_name: GitHub Actions + committer_email: actions@github.com + add: .ci-config/rippled.cfg + - name: Run docker in background run: | docker run --detach --rm -p 5005:5005 -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "rippled -a" diff --git a/tools/fetch_rippled_amendments.py b/tools/fetch_rippled_amendments.py new file mode 100644 index 000000000..9d18431e8 --- /dev/null +++ b/tools/fetch_rippled_amendments.py @@ -0,0 +1,72 @@ +""" +This script fetches the latest amendments from (the `develop` branch of) rippled and +adds them to the `rippled.cfg` file. +""" + +import configparser +import os +import re + +import requests + +CONFIG_FILE = os.path.join(os.getcwd(), ".ci-config", "rippled.cfg") +FEATURES_SECTION = "features" +RIPPLED_FEATURES_FILE = "https://raw.githubusercontent.com/XRPLF/rippled/develop/include/xrpl/protocol/detail/features.macro" + +config = configparser.ConfigParser( + allow_no_value=True, +) +config.optionxform = str # type: ignore +config.read(CONFIG_FILE) + + +def fetch_rippled_amendments(): + # Send a GET request + response = requests.get(RIPPLED_FEATURES_FILE, timeout=30) # 30 second timeout + + # Check for successful request + if response.status_code == 200: + features_contents = response.text + feature_hits = re.findall( + r"^ *XRPL_FEATURE *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default[Yes|No]", + features_contents, + re.MULTILINE, + ) + + fix_hits = re.findall( + r"^ *XRPL_FIX *\(([a-zA-Z0-9_]+), * Supported::yes,", + features_contents, + re.MULTILINE, + ) + + all_supported_amendments = feature_hits + ["fix" + f for f in fix_hits] + return all_supported_amendments + else: + print(f"Failed to fetch file. Status code: {response.status_code}") + + +if __name__ == "__main__": + if FEATURES_SECTION in config: + amendments_to_add = [] + existing_amendments = [v for v in config[FEATURES_SECTION] if v] + new_rippled_amendments = fetch_rippled_amendments() + + for v in new_rippled_amendments: + if v not in existing_amendments: + amendments_to_add.append(v) + + if len(amendments_to_add) > 0: + print( + "INFO: The following amendments need to be inserted into the config file: " + + ", ".join(amendments_to_add) + ) + + for v in amendments_to_add: + config.set(FEATURES_SECTION, v, value=None) + + with open(CONFIG_FILE, "w", encoding="utf-8") as rippled_cfg_file: + config.write(rippled_cfg_file) + else: + print(f"INFO: No new amendments to add into the {CONFIG_FILE} file.") + else: + print(f"ERROR: No features section found in the {CONFIG_FILE} file.") From 4469f7bde257e3a65bc529f7762f8359c93ccf59 Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S Date: Mon, 7 Apr 2025 15:18:12 -0700 Subject: [PATCH 2/7] Re-arrange the Github Actions steps --- .github/workflows/integration_test.yml | 35 +++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 749097019..1daaa9d4b 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -23,7 +23,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Load cached .local id: cache-poetry uses: actions/cache@v4 @@ -31,23 +30,6 @@ jobs: path: /home/runner/.local key: dotlocal-${{ env.POETRY_VERSION }} - - name: Fetch latest rippled amendments - if: ${{ github.event_name == 'pull_request' }} - run: | - poetry run python tools/fetch_rippled_amendments.py - - - name: Add and commit rippled.cfg - uses: EndBug/add-and-commit@v9 - with: - message: 'Update rippled.cfg with latest amendments' - committer_name: GitHub Actions - committer_email: actions@github.com - add: .ci-config/rippled.cfg - - - name: Run docker in background - run: | - docker run --detach --rm -p 5005:5005 -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "rippled -a" - - name: Install poetry if: steps.cache-poetry.outputs.cache-hit != 'true' run: | @@ -67,6 +49,23 @@ jobs: - name: Install poetry dependencies run: poetry install + - name: Fetch latest rippled amendments + if: ${{ github.event_name == 'pull_request' }} + run: | + poetry run python tools/fetch_rippled_amendments.py + + - name: Add and commit rippled.cfg + uses: EndBug/add-and-commit@v9 + with: + message: 'Update rippled.cfg with latest amendments' + committer_name: GitHub Actions + committer_email: actions@github.com + add: .ci-config/rippled.cfg + + - name: Run docker in background + run: | + docker run --detach --rm -p 5005:5005 -p 6006:6006 --volume "${{ github.workspace }}/.ci-config/":"/etc/opt/ripple/" --name rippled-service --health-cmd="rippled server_info || exit 1" --health-interval=5s --health-retries=10 --health-timeout=2s --env GITHUB_ACTIONS=true --env CI=true --entrypoint bash ${{ env.RIPPLED_DOCKER_IMAGE }} -c "rippled -a" + - name: Integration test run: | poetry run poe test_integration From 0b0f8a09f969fc6ee811265d4e66aa4845c000b1 Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S Date: Mon, 7 Apr 2025 15:25:40 -0700 Subject: [PATCH 3/7] Github Actions: checkout a brach name; fix the detached HEAD error --- .github/workflows/integration_test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 1daaa9d4b..9561854c2 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -22,6 +22,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + ref: ${{ github.event.pull_request.head.ref }} - name: Load cached .local id: cache-poetry @@ -55,9 +58,12 @@ jobs: poetry run python tools/fetch_rippled_amendments.py - name: Add and commit rippled.cfg + if: ${{ github.event_name == 'pull_request' }} uses: EndBug/add-and-commit@v9 with: message: 'Update rippled.cfg with latest amendments' + author_name: GitHub Actions + author_email: actions@github.com committer_name: GitHub Actions committer_email: actions@github.com add: .ci-config/rippled.cfg From 82693e6d904b0b32164316df0bc4fda5d4234490 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Mon, 7 Apr 2025 22:26:03 +0000 Subject: [PATCH 4/7] Update rippled.cfg with latest amendments --- .ci-config/rippled.cfg | 76 ++++++++---------------------------------- 1 file changed, 13 insertions(+), 63 deletions(-) diff --git a/.ci-config/rippled.cfg b/.ci-config/rippled.cfg index c266a72fa..77d0eb5b4 100644 --- a/.ci-config/rippled.cfg +++ b/.ci-config/rippled.cfg @@ -3,13 +3,6 @@ port_rpc_admin_local port_ws_public port_ws_admin_local -# port_peer -# port_ws_admin_local -# ssl_key = /etc/ssl/private/server.key -# ssl_cert = /etc/ssl/certs/server.crt - -# IPs must be 0.0.0.0 instead of 127.0.0.1 to be accessed outside the docker container - [port_rpc_admin_local] port = 5005 ip = 0.0.0.0 @@ -21,11 +14,6 @@ port = 80 ip = 0.0.0.0 protocol = ws -# [port_peer] -# port = 51235 -# ip = 0.0.0.0 -# protocol = peer - [port_ws_admin_local] port = 6006 ip = 0.0.0.0 @@ -35,26 +23,13 @@ protocol = ws [node_size] small -# tiny -# small -# medium -# large -# huge - [node_db] -type=NuDB -path=/var/lib/rippled/db/nudb -advisory_delete=0 - -# How many ledgers do we want to keep (history)? -# Integer value that defines the number of ledgers -# between online deletion events -online_delete=256 +type = NuDB +path = /var/lib/rippled/db/nudb +advisory_delete = 0 +online_delete = 256 [ledger_history] -# How many ledgers do we want to keep (history)? -# Integer value (ledger count) -# or (if you have lots of TB SSD storage): 'full' 256 [database_path] @@ -76,41 +51,15 @@ r.ripple.com 51235 validators.txt [rpc_startup] -{ "command": "log_level", "severity": "info" } - -# severity (order: lots of information .. only errors) -# debug -# info -# warn -# error -# fatal +{ "command" = "log_level", "severity": "info" } [ssl_verify] 1 -# The [features] stanza does not currently work for standalone mode: https://github.com/XRPLF/xrpl-dev-portal/issues/1762#issuecomment-1441252450 - - -# In order to enable an amendment which by default would vote "No", you must include its amendment id and name here. -# To add amendments specifically from the latest releases of rippled: -# 1. Go to https://xrpl.org/known-amendments.html -# 2. Find the first amendment in the latest releases of rippled which are not already in the list below -# 3. Click on each amendment to get their Amendment ID and name to add to this list manually. -# You will likely update the list with all amendments from a new release of rippled all at once. - -# To get the list of amendments on a network (e.g. devnet) follow the steps in xrpl.js's CONTRIBUTING.md for "Updating the Docker container". -# https://github.com/XRPLF/xrpl.js/blob/main/CONTRIBUTING.md -# (Running the script `getNewAmendments.js` should help you identify any new amendments that should be added.) -# -# Note: The version of rippled you use this config with must have an implementation for the amendments you attempt to enable or it will crash. -# If you need the version of rippled to be more up to date, you may need to make a comment on this repo: https://github.com/WietseWind/docker-rippled - -# network_id is required otherwise it's read as None [network_id] 63456 [features] -# Devnet amendments as of June 28th, 2023 NegativeUNL fixRemoveNFTokenAutoTrustLine NonFungibleTokensV1 @@ -157,24 +106,19 @@ fix1373 MultiSign Checks NonFungibleTokensV1_1 -# 1.10.0 Amendments DisallowIncoming fixNonFungibleTokensV1_2 fixTrustLinesToSelf fixUniversalNumber ImmediateOfferKilled XRPFees -# 1.11.0 Amendments ExpandedSignerList -# 1.12.0 Amendments AMM Clawback fixReducedOffersV1 fixNFTokenRemint -# 2.0.0-b4 Amendments XChainBridge DID -# 2.2.0-b3 Amendments fixNFTokenReserve fixInnerObjTemplate fixAMMOverflowOffer @@ -182,7 +126,6 @@ PriceOracle fixEmptyDID fixXChainRewardRounding fixPreviousTxnID -# 2.3.0 Amendments fixAMMv1_1 fixAMMv1_2 AMMClawback @@ -196,9 +139,16 @@ fixEnforceNFTokenTrustline fixReducedOffersV2 DeepFreeze PermissionedDomains +DynamicNFT +fixInvalidTxFlags +fixFrozenLPTokenTransfer +fixFillOrKill +fixDisallowIncomingV1 +fixNFTokenNegOffer +fixNFTokenDirV1 -# This section can be used to simulate various FeeSettings scenarios for rippled node in standalone mode [voting] reference_fee = 200 # 200 drops account_reserve = 20000000 # 20 XRP owner_reserve = 5000000 # 5 XRP + From a53ed6c579254f830fb45387ca9180798adc050f Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S <21219765+ckeshava@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:04:23 -0700 Subject: [PATCH 5/7] Update tools/fetch_rippled_amendments.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- tools/fetch_rippled_amendments.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/fetch_rippled_amendments.py b/tools/fetch_rippled_amendments.py index 9d18431e8..43b98ef82 100644 --- a/tools/fetch_rippled_amendments.py +++ b/tools/fetch_rippled_amendments.py @@ -28,10 +28,11 @@ def fetch_rippled_amendments(): if response.status_code == 200: features_contents = response.text feature_hits = re.findall( - r"^ *XRPL_FEATURE *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default[Yes|No]", - features_contents, - re.MULTILINE, - ) + feature_hits = re.findall( + r"^ *XRPL_FEATURE *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default(Yes|No)", + features_contents, + re.MULTILINE, + ) fix_hits = re.findall( r"^ *XRPL_FIX *\(([a-zA-Z0-9_]+), * Supported::yes,", From cc6b7978e79f75e69b2385dc8de97b38df61e88e Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S <21219765+ckeshava@users.noreply.github.com> Date: Mon, 7 Apr 2025 16:04:48 -0700 Subject: [PATCH 6/7] Update tools/fetch_rippled_amendments.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- tools/fetch_rippled_amendments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/fetch_rippled_amendments.py b/tools/fetch_rippled_amendments.py index 43b98ef82..1b9a3f452 100644 --- a/tools/fetch_rippled_amendments.py +++ b/tools/fetch_rippled_amendments.py @@ -44,7 +44,7 @@ def fetch_rippled_amendments(): return all_supported_amendments else: print(f"Failed to fetch file. Status code: {response.status_code}") - + return [] if __name__ == "__main__": if FEATURES_SECTION in config: From 4236ca6a648bcaf98abb5e7b2e64663bab02e56e Mon Sep 17 00:00:00 2001 From: Chenna Keshava B S Date: Mon, 7 Apr 2025 16:13:35 -0700 Subject: [PATCH 7/7] Use non-capturing groups in regex --- tools/fetch_rippled_amendments.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tools/fetch_rippled_amendments.py b/tools/fetch_rippled_amendments.py index 1b9a3f452..c82c834f4 100644 --- a/tools/fetch_rippled_amendments.py +++ b/tools/fetch_rippled_amendments.py @@ -6,6 +6,7 @@ import configparser import os import re +import sys import requests @@ -21,36 +22,37 @@ def fetch_rippled_amendments(): - # Send a GET request - response = requests.get(RIPPLED_FEATURES_FILE, timeout=30) # 30 second timeout - - # Check for successful request + response = requests.get(RIPPLED_FEATURES_FILE, timeout=30) if response.status_code == 200: features_contents = response.text feature_hits = re.findall( - feature_hits = re.findall( - r"^ *XRPL_FEATURE *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default(Yes|No)", - features_contents, - re.MULTILINE, - ) + r"^ *XRPL_FEATURE *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default(?:Yes|No)", + features_contents, + re.MULTILINE, + ) fix_hits = re.findall( - r"^ *XRPL_FIX *\(([a-zA-Z0-9_]+), * Supported::yes,", + r"^ *XRPL_FIX *\(([a-zA-Z0-9_]+), * Supported::yes, VoteBehavior::Default(?:Yes|No)", features_contents, re.MULTILINE, ) - all_supported_amendments = feature_hits + ["fix" + f for f in fix_hits] + print(fix_hits) + + all_supported_amendments = feature_hits + ["fix" + f for f in fix_hits if f] return all_supported_amendments else: print(f"Failed to fetch file. Status code: {response.status_code}") - return [] + if __name__ == "__main__": if FEATURES_SECTION in config: amendments_to_add = [] existing_amendments = [v for v in config[FEATURES_SECTION] if v] new_rippled_amendments = fetch_rippled_amendments() + if new_rippled_amendments is None: + print("ERROR: Failed to fetch rippled amendments.") + sys.exit(1) for v in new_rippled_amendments: if v not in existing_amendments: