Retire fixTrustLinesToSelf - #5989
Conversation
|
The code is here but we need to double check if there's no buggy trust lines so I'll update later. |
So there are 2 trust lines that the high account is the same as the low account, which means that we can't fully retire the feature at this moment, and we should at least keep the part that deletes such trust lines if we want to do it now but that doesn't look tidy - or, we could probably modify the |
|
Attaching my script here: #!/usr/bin/env python3
"""
Fetch all RippleState trust lines from a given XRP Ledger ledger
and return only those where LowLimit.issuer == HighLimit.issuer.
Notes
- Uses JSON-RPC over HTTP POST to the server (e.g. Ripple's public Clio).
- Ignores any 'id' field from examples; not needed.
- Forces type = "RippleState" and binary = false.
- Handles both plain and 'FinalFields' wrapped entries.
- Streams results to a JSONL file to avoid high memory usage.
Example:
python find_same_issuer_trustlines.py \
--server https://s1.ripple.com:51234 \
--ledger-hash 842B57C1CC0613299A686D3E9F310EC0422C84D3911E5056389AA7E5808A93C8 \
--out matches.jsonl
"""
import argparse
import json
import sys
import time
from typing import Any, Dict, Iterable, Optional
import requests
def build_request_payload(
ledger_hash: Optional[str],
ledger_index: Optional[str],
limit: int,
marker: Optional[str],
) -> Dict[str, Any]:
payload: Dict[str, Any] = {
"method": "ledger_data",
"params": [
{
"type": "RippleState",
"binary": False,
"limit": limit,
}
],
}
p = payload["params"][0]
if ledger_hash:
p["ledger_hash"] = ledger_hash
if ledger_index:
p["ledger_index"] = ledger_index
if marker:
p["marker"] = marker
return payload
def unwrap_fields(le: Dict[str, Any]) -> Dict[str, Any]:
"""
ledger_data may return entries either as flat fields or under FinalFields.
This normalises to the effective final fields.
"""
if "FinalFields" in le and isinstance(le["FinalFields"], dict):
return le["FinalFields"]
return le
def same_issuer(le: Dict[str, Any]) -> bool:
"""
Returns True if this RippleState entry has the same issuer on both sides.
"""
f = unwrap_fields(le)
low = f.get("LowLimit", {})
high = f.get("HighLimit", {})
try:
return (
isinstance(low, dict)
and isinstance(high, dict)
and low.get("issuer") is not None
and high.get("issuer") is not None
and str(low["issuer"]) == str(high["issuer"])
)
except Exception:
return False
def fetch_pages(
server: str,
ledger_hash: Optional[str],
ledger_index: Optional[str],
limit: int,
request_timeout: float,
pause_between: float,
) -> Iterable[Dict[str, Any]]:
"""
Iterates over all pages returned by ledger_data with type RippleState.
Yields individual ledger entries.
"""
marker: Optional[str] = None
session = requests.Session()
while True:
payload = build_request_payload(ledger_hash, ledger_index, limit, marker)
try:
resp = session.post(server, json=payload, timeout=request_timeout)
except requests.RequestException as e:
raise SystemExit(f"HTTP error talking to {server}: {e}") from e
if resp.status_code != 200:
raise SystemExit(f"Non-200 status {resp.status_code}: {resp.text}")
try:
data = resp.json()
except ValueError:
raise SystemExit("Response was not valid JSON")
result = data.get("result")
if not isinstance(result, dict):
raise SystemExit(f"Unexpected response shape: {json.dumps(data)[:500]}")
state = result.get("state", [])
if not isinstance(state, list):
raise SystemExit(f"Unexpected 'state' shape: {json.dumps(result)[:500]}")
for le in state:
# Filter by LedgerEntryType just in case
typ = le.get("LedgerEntryType") or unwrap_fields(le).get("LedgerEntryType")
if typ == "RippleState":
yield le
marker = result.get("marker")
if not marker:
break
if pause_between > 0:
time.sleep(pause_between)
def main() -> None:
ap = argparse.ArgumentParser(description="Find RippleState trust lines with same issuer on both sides.")
ap.add_argument("--server", default="https://s1.ripple.com:51234",
help="JSON-RPC endpoint URL for rippled/Clio (default: Ripple public Clio)")
g = ap.add_mutually_exclusive_group()
g.add_argument("--ledger-hash", help="Specific ledger hash to scan")
g.add_argument("--ledger-index", help="Specific ledger index to scan (e.g. 'validated' or a number)")
ap.add_argument("--limit", type=int, default=200,
help="Page size for ledger_data requests (max server-dependent, default 200)")
ap.add_argument("--out", default="matches.jsonl",
help="Output JSONL file for matching entries")
ap.add_argument("--timeout", type=float, default=30.0,
help="HTTP request timeout seconds (default 30)")
ap.add_argument("--pause", type=float, default=0.0,
help="Pause seconds between pages to be gentle (default 0)")
args = ap.parse_args()
if not args.ledger_hash and not args.ledger_index:
print("Tip: you did not specify --ledger-hash or --ledger-index. Defaulting to 'validated'.", file=sys.stderr)
args.ledger_index = "validated"
total = 0
matched = 0
with open(args.out, "w", encoding="utf-8") as fh:
for le in fetch_pages(
server=args.server,
ledger_hash=args.ledger_hash,
ledger_index=args.ledger_index,
limit=args.limit,
request_timeout=args.timeout,
pause_between=args.pause,
):
total += 1
if same_issuer(le):
matched += 1
fh.write(json.dumps(le, ensure_ascii=False) + "\n")
print(f"Scanned RippleState entries: {total}")
print(f"Matches where LowLimit.issuer == HighLimit.issuer: {matched}")
print(f"Wrote matches to: {args.out}")
if __name__ == "__main__":
main() |
|
@a1q123456 Can you post just the ledger entry IDs of the objects your script found? They should have been impossible to create, so I'm wondering if the amendment actually failed to do what it was supposed to. |
I think I was checking against an old ledger, and they don't exist anymore now. The ledger entry hash are |
|
Checked against the ledger |
Signed-off-by: JCW <a1q123456@users.noreply.github.com> # Conflicts: # include/xrpl/protocol/detail/features.macro
974645d to
bfe8df3
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #5989 +/- ##
=========================================
+ Coverage 78.2% 78.3% +0.1%
=========================================
Files 816 816
Lines 68948 68887 -61
Branches 8352 8303 -49
=========================================
- Hits 53950 53942 -8
+ Misses 14998 14945 -53
🚀 New features to boost your workflow:
|
…inez/lending-XLS-66 * mywork/ximinez/lending-number: Catch up the consequences of Number changes Fix build error - avoid copy Add integer enforcement when converting to XRP/MPTAmount to Number Make all STNumber fields "soeDEFAULT" Add optional enforcement of valid integer range to Number fix: domain order book insertion #5998 refactor: Retire fixTrustLinesToSelf amendment (#5989)
Amendments activated for more than 2 years can be retired. This change retires the fixTrustLinesToSelf amendment.
High Level Overview of Change
Context of Change
Type of Change
.gitignore, formatting, dropping support for older tooling)API Impact
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)