Skip to content

small changes#996

Open
ledhed2222 wants to merge 2 commits into
XRPLF:mainfrom
ledhed2222:small-changes
Open

small changes#996
ledhed2222 wants to merge 2 commits into
XRPLF:mainfrom
ledhed2222:small-changes

Conversation

@ledhed2222

Copy link
Copy Markdown
Contributor

High Level Overview of Change

just looking at the state of repo and noticed a few easy changes :)

Context of Change

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Release

Did you update CHANGELOG.md?

  • Yes
  • No, this change does not impact library users

Test Plan

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7bdb724a-3db4-487c-8799-6a671ba60ad5

📥 Commits

Reviewing files that changed from the base of the PR and between 2528024 and e00bd31.

📒 Files selected for processing (7)
  • CONTRIBUTING.md
  • xrpl/constants.py
  • xrpl/core/keypairs/ed25519.py
  • xrpl/core/keypairs/helpers.py
  • xrpl/core/keypairs/secp256k1.py
  • xrpl/models/transactions/nftoken_mint.py
  • xrpl/models/transactions/nftoken_modify.py
✅ Files skipped from review due to trivial changes (2)
  • xrpl/core/keypairs/helpers.py
  • xrpl/models/transactions/nftoken_mint.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • xrpl/core/keypairs/ed25519.py
  • xrpl/constants.py
  • xrpl/models/transactions/nftoken_modify.py
  • xrpl/core/keypairs/secp256k1.py

Walkthrough

This PR consolidates NFT URI validation by extracting a hardcoded 512-byte limit to a shared constant, standardizes key padding logic across ed25519 and secp256k1 keypair implementations, and includes minor documentation updates to Python environment setup instructions.

Changes

NFT URI Consolidation and Keypairs Refactoring

Layer / File(s) Summary
NFT URI Constant Definition and Adoption
xrpl/constants.py, xrpl/models/transactions/nftoken_mint.py, xrpl/models/transactions/nftoken_modify.py
Introduces MAX_NFT_URI_LENGTH: Final[int] = 512 as a shared public constant. Both NFToken models now import and use it for URI length validation instead of module-local constants.
Ed25519 Key Formatting Standardization
xrpl/core/keypairs/ed25519.py
Adds _KEY_LENGTH constant and updates _format_key to consistently left-pad key strings via zfill(_KEY_LENGTH) instead of conditionally padding only when input is shorter than 64 characters.
Secp256k1 Key Formatting Standardization
xrpl/core/keypairs/secp256k1.py
Removes _PADDING_PREFIX constant and updates _format_key to use left-padding via zfill(_KEY_LENGTH), aligning the padding behavior with ed25519.
Account ID Hash Computation Refactor
xrpl/core/keypairs/helpers.py
Refactors get_account_id to inline SHA-256 and RIPEMD160 digest computation into a single return expression, removing the intermediate sha_hash variable.
Python Environment Setup Documentation
CONTRIBUTING.md
Adds alternative setup instruction for contributors already using pyenv to run pyenv local 3.11.6 in the current directory.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • XRPLF/xrpl-py#799 — Originally introduced NFTokenModify with the 512-byte URI length constraint that is now consolidated into a shared constant.

Suggested reviewers

  • Patel-Raj11
  • pdp2121
  • mvadari
  • ckeshava

Poem

🐰 A constant hops from place to place,
Five-twelve bytes find their proper base,
Keys are padded, formatted clean,
The nicest refactors I've seen! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'small changes' is vague and generic, using non-descriptive language that fails to convey what was actually changed in the pull request. Replace with a specific, descriptive title such as 'Centralize NFT URI length constant' or 'Extract MAX_NFT_URI_LENGTH to shared constants' that reflects the main functional change.
Description check ❓ Inconclusive The description leaves critical sections blank (Context of Change, Test Plan) and lacks specific detail about what changes were made and why, despite the template requesting this information. Fill in the Context of Change section explaining why the NFT constant was centralized and why key formatting was updated, and describe how the changes were tested.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@xrpl/constants.py`:
- Around line 85-88: The docstring for the constant MAX_NFT_URI_LENGTH is
incorrect about units: update the docstring for MAX_NFT_URI_LENGTH to state that
512 is a hex-character limit (not bytes) and optionally note it corresponds to
256 bytes (256 bytes × 2 hex chars/byte) to match the XRPL spec and downstream
error messages; locate the constant MAX_NFT_URI_LENGTH in xrpl/constants.py and
replace the "in bytes" wording with "in hex characters (corresponds to 256
bytes)".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e8676709-0e2d-4f25-8f7f-0371d36a8020

📥 Commits

Reviewing files that changed from the base of the PR and between a68a2f0 and 2528024.

📒 Files selected for processing (7)
  • CONTRIBUTING.md
  • xrpl/constants.py
  • xrpl/core/keypairs/ed25519.py
  • xrpl/core/keypairs/helpers.py
  • xrpl/core/keypairs/secp256k1.py
  • xrpl/models/transactions/nftoken_mint.py
  • xrpl/models/transactions/nftoken_modify.py

Comment thread xrpl/constants.py
@Patel-Raj11

Copy link
Copy Markdown
Collaborator

@ledhed2222 Looks like there are some changes that modify actual source code. Can you elaborate in the PR description about context of each change and it's purpose.

@ledhed2222

ledhed2222 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@Patel-Raj11 yes i'm mostly putting the nft max length in a shared location so that mint and modify txns can reuse the constant. otherwise it's cosmetic code changes that i believe speak for themselves. but i'm happy to annotate each with comments if that is useful for you

also note that i'm editing code that i wrote originally mostly ;)

"""
sha_hash = hashlib.sha256(public_key).digest()
return bytes(RIPEMD160.new(sha_hash).digest())
return bytes(RIPEMD160.new(hashlib.sha256(public_key).digest()).digest())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semgrep identified an issue in your code:

RIPEMD160 hash algorithm used in get_account_id is cryptographically broken and vulnerable to collision attacks that could allow account ID spoofing.

More details about this

The get_account_id function uses RIPEMD160, a cryptographic hash algorithm that has known weaknesses and is no longer considered secure for protecting sensitive data.

Exploit scenario:

  1. An attacker collects multiple public keys and their corresponding account IDs generated by this function.
  2. The attacker exploits known collision vulnerabilities in RIPEMD160 to find two different public keys that produce the same account ID hash.
  3. By providing a crafted public key, the attacker can impersonate another account since the collision causes both keys to map to the same account_id.
  4. This allows the attacker to hijack transactions or access resources intended for the legitimate account holder.

The chained hashing (SHA-256 followed by RIPEMD160) does provide some additional protection compared to RIPEMD160 alone, but RIPEMD160's cryptographic weaknesses mean this implementation remains vulnerable to collision attacks that could compromise account identity verification.

To resolve this comment:

💡 Follow autofix suggestion

Suggested change
return bytes(RIPEMD160.new(hashlib.sha256(public_key).digest()).digest())
return bytes(SHA3_512.new(hashlib.sha256(public_key).digest()).digest())
View step-by-step instructions
  1. Check whether this account_id format is required to match an external protocol or network format.
    If this value must remain compatible with XRPL account IDs, you cannot safely replace RIPEMD160 without also changing the protocol contract for every caller that consumes this value.

  2. If this hash is only used internally, replace RIPEMD160 with a modern hash from the standard library, such as hashlib.sha256(...), hashlib.sha3_256(...), or hashlib.blake2b(..., digest_size=32).
    For example, change the second hash from RIPEMD160.new(...) to a hashlib call over the existing hashlib.sha256(public_key).digest() result.

  3. Remove the import Crypto.Hash.RIPEMD160 as RIPEMD160 import after you stop using it.
    This keeps the function on supported hash primitives and avoids keeping insecure crypto dependencies in use.

  4. Update the function contract if needed, because replacing RIPEMD160 changes the output size from 20 bytes to a larger value such as 32 bytes.
    If callers expect a fixed-length identifier, make that new size explicit in the docstring and in any serialization logic that stores or transmits the value.

  5. Alternatively, if you must keep a 20-byte internal identifier but do not need XRPL compatibility, derive it from a modern hash instead of RIPEMD160, such as taking the first 20 bytes of hashlib.sha256(...).digest().
    This is still based on a stronger hash family, but only use this if every producer and consumer of the identifier can be updated together.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by pycryptodome-sha1-or-ripemd160.

You can view more details about this finding in the Semgrep AppSec Platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants