Skip to content

fix(accounts): normalize address in raw-SQL balance operations - #1773

Closed
Alicepoltora wants to merge 3 commits into
genlayerlabs:v0.123-devfrom
Alicepoltora:fix/account-balance-address-normalization
Closed

Alicepoltora wants to merge 3 commits into
genlayerlabs:v0.123-devfrom
Alicepoltora:fix/account-balance-address-normalization

Conversation

@Alicepoltora

@Alicepoltora Alicepoltora commented Sep 22, 2026 •

Copy link
Copy Markdown

Problem

Account rows are keyed by the checksummed address: create_new_account_with_address() and get_account() run every address through to_checksum_address(). But the raw-SQL balance paths — debit_account_balance(), credit_account_balance(), credit_tx_value_once() — used the address verbatim.

Any caller passing a non-checksummed address (e.g. lowercase, as users commonly send in JSON-RPC — see _sandbox_debit_sender in endpoints.py):

  • credit_account_balance(lower_addr): INSERT ... ON CONFLICT (id) DO NOTHING does not conflict with the checksummed row → creates a duplicate account row keyed by the lowercase address, and the credit lands on that duplicate. Balance gets split across two rows for the same address.
  • debit_account_balance(lower_addr): WHERE id = lower_addr matches nothing → silently returns False (insufficient balance) even though the account has funds.
  • refund_tx_value(): credits the refund to the lowercase duplicate row instead of the sender's real account.

Fix

Added _normalize_address() (checksum with the same fallback-on-error semantics that get_account() already used) and applied it to every raw-SQL balance path.

Tests

New tests/unit/test_accounts_manager_normalization.py (mocked session, no DB needed):

  • test_credit_normalizes_address_before_insert_and_update and test_debit_normalizes_address and test_credit_tx_value_once_normalizes_target — fail on main, pass with the fix
  • test_credit_zero_or_negative_amount_is_noop — no-op behavior preserved
  • test_normalize_fallback_keeps_original — non-address values pass through unchanged (backwards compatibility)

Summary by CodeRabbit

  • Bug Fixes
    • Improved account address handling so balance queries and updates consistently use checksummed addresses.
    • Preserved the original address when checksum conversion is not possible.
    • Prevented database updates for zero or negative credit amounts.

debit_account_balance(), credit_account_balance() and
credit_tx_value_once() execute raw SQL keyed by the address, but unlike
get_account()/create_new_account_with_address() they never passed the
address through to_checksum_address(). Accounts are stored keyed by the
checksummed id, so a caller passing a lowercase address (e.g. from a JSON-RPC
'from' field) would:

- debit_account_balance(): match no row and silently return False even when
  the account has sufficient balance;
- credit_account_balance(): hit ON CONFLICT DO NOTHING on the checksummed
  row's id and instead INSERT a new duplicate row keyed by the lowercase
  address, splitting the balance across two accounts;
- refund_tx_value(): credit the refund onto the lowercase duplicate row,
  losing the funds from the sender's perspective.

_normalize_address() centralizes the to_checksum_address() normalization
with the same fallback-on-error semantics get_account() already used, and
is applied to every raw-SQL balance path. Unit tests (no DB required)
verify the SQL parameters are normalized and that non-address values are
passed through unchanged.
@github-actions
github-actions Bot changed the base branch from main to v0.123-dev September 22, 2026 13:05
@github-actions

Copy link
Copy Markdown
Contributor

This PR targeted main, which is only the default/static branch.

I retargeted it to v0.123-dev, the active development branch. Pushes to v0.123-dev automatically fast-forward main.

@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 99ed3ec2-97e4-442f-a8f2-938fcaf570bd

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

# Conflicts:
#	backend/database_handler/accounts_manager.py
@danieljrc888

Copy link
Copy Markdown
Contributor

Thanks! Since this was opened, #1748 added inline checksumming to debit_account_balance and credit_account_balance, which conflicted here. I merged current v0.123-dev into the branch (e6da79fe) and resolved it by keeping your _normalize_address helper for all three methods and dropping the duplicate inline try/except. The part still missing on dev was credit_tx_value_once (used by sim_fundAccount and the consensus activation credit), and your test proves it. tests/unit/: 1677 passed, 7 skipped.

@danieljrc888 danieljrc888 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.

Reviewed for the v0.123 release candidate; unit suite and CI green.

@danieljrc888

Copy link
Copy Markdown
Contributor

/run-e2e all

Frozen landing cut: #1773 alone, head a91e6bbfedbdc74f8dca1cbcd489192959c6a662 over v0.123-dev@e59ddfbaa15f19a2d856f184e3e27a30c3007cb2; no cross-repository Depends-On. Full component and stack coverage (no stack selector). Native CI is green. Merge is authorized once this E2E is green.

danieljrc888 added a commit that referenced this pull request Oct 21, 2026
Lands four reviewed fork PRs together after a full E2E run on this exact head:

- #1765: redact validator private keys from call receipts and explorer payloads
- #1715: bind postgres, redis and ollama host ports to loopback
- #1773: normalize addresses in raw-SQL balance operations
- #1789: normalize the address in sim_fundAccount

Co-authored-by: Kanan <93033289+kriss39@users.noreply.github.com>
Co-authored-by: Starling <82058629+Starling-spell@users.noreply.github.com>
Co-authored-by: Alicepoltora <Alicepoltora@users.noreply.github.com>
@danieljrc888

Copy link
Copy Markdown
Contributor

Landed in v0.123-dev via #1797 (squash 9e907cd), which combined #1765, #1715, #1773 and #1789 at their reviewed heads and passed full E2E. Your commits are credited with Co-authored-by. Thanks for the fix!

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