Fix bridge initiate miner source validation#6787
Conversation
|
CI note for reviewers:
Touched files here are limited to |
zqleslie
left a comment
There was a problem hiding this comment.
Code Review Bounty Claim — RustChain PR #6787
Bounty: #73 Code Review Bounty Program
Reviewer: zqleslie
RTC wallet: XKO212dF8324b9b61F294D26A6Dc68e3f81e4BE451D
Reviewed PR
- PR: #6787
- Review state:
APPROVED
Review performed
Reviewed the bridge initiate miner source validation fix:
-
Auth-before-validation ordering — The key fix moves
RC_ADMIN_KEYchecks ahead of address-format validation for deposits. Previously, a valid miner ID likeRTC_test_minerwould hitvalidate_chain_address_format()first and fail with400, masking whether the request was actually authorized. Now auth errors surface correctly as401/503. -
Route-specific address validation — The new
validate_bridge_route_address()helper correctly usesvalidate_miner_id_format()for RustChain deposit source miner IDs, while keeping strictRTC+ 40-hex validation for all other cases. Therustchain_source_is_minerboolean gate is clean and scoped to deposits where the source is RustChain. -
No auth bypass —
RC_ADMIN_KEYcomparison useshmac.compare_digest()(timing-safe). Admin key is still required for deposits. The fix only changes error ordering, not authorization logic. -
Test fixture update —
test_valid_rustchain_addressnow usesRTC+ 40 a's instead ofRTC_test123abc, aligning with the strict faucet-format validator. Good. -
Diff size — +31/-14 across 2 files. Focused, no unrelated changes.
No blocking issues found. Safe to merge.
This is a claim only. No payout asserted here.
jaxint
left a comment
There was a problem hiding this comment.
Great contribution! 🔍 Reviewed and looks solid.
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing to RustChain. Approved.
⏸️ Tri-brain review — good idea, one blocking edge caseSeparating miner_id from wallet on bridge routes is the right fix (anti-IDOR). But Grok caught a logic bug: [BLOCKING] source/dest distinction is value-based, not position-based. [SHOULD-FIX] Add tests (Codex): a RustChain deposit accepts a valid miner_id source, rejects a wallet address as source, still requires a wallet-form destination, and the rustchain→rustchain case keeps the dest as a wallet. Fix the position-vs-value bug + add those tests and I'll merge — the validation itself is sound. |
Code Review for PR #6787Files reviewed: 2 files (+31/-14) Files examined:
General observations:
Assessment:
Recommendation: Looks good to merge. Wallet for bounty: jesusmp Claiming code review bounty. Review completed on all 2 changed files. |
jaxint
left a comment
There was a problem hiding this comment.
Well done! This contribution adds real value to the project.
jaxint
left a comment
There was a problem hiding this comment.
LGTM! Thanks for contributing to RustChain. Approved.
BossChaos
left a comment
There was a problem hiding this comment.
Code Review — PR #6787: Fix bridge initiate miner source validation
Reviewer: BossChaos (subagent)
Files changed: node/bridge_api.py (+30/-13), tests/test_bridge_lock_ledger.py (+1/-1)
Summary
Two bugs are fixed in a single PR:
-
Auth masked by validation — The original
initiate_bridge()route checked address-format validity before operator authorization. An unauthenticated deposit request from a miner with an unconventional source address (e.g.,RTC_test_miner) would get a400from the strict^RTC[0-9a-fA-F]{40}$regex before ever reaching the401/503auth check. This leaks miner-ID enumeration and confuses callers about the actual failure mode. -
Wrong validator used for miner IDs —
validate_chain_address_format("rustchain", addr)enforces canonical wallet-address format (40 hex chars), butbalances.miner_idvalues include non-canonical identifiers (e.g.,RTC_test_miner). Applying the wallet-address regex to miner IDs caused valid miners to be rejected at the address-validation step, long before any business-logic check.
Changes — node/bridge_api.py
| Line | Change | Assessment |
|---|---|---|
| +1 | New validate_bridge_route_address() dispatcher — delegates to validate_miner_id_format() when the address is a RustChain deposit source (miner ID), otherwise falls through to validate_chain_address_format() |
Correct. Preserves strict wallet-address validation for all non-miner-ID RustChain addresses and for all other chains. |
| +2-5 | Moved admin-key check before address-format validation in initiate_bridge() |
Correct. Ensures auth errors are returned first, preventing validation-behavior leakage to unauthenticated callers. The expected_admin_key check still yields 503 when unconfigured and 401 when present but mismatched, in both cases before any address validation runs. |
| +6-16 | Replaced the hardcoded validate_chain_address_format() loop with a call to validate_bridge_route_address(), passing rustchain_source_is_miner=True only when the address is the RustChain source in a deposit direction |
Correct. The boolean condition is precise: it fires only for the one address in the one direction where source_address == miner_id. |
| -7 | Removed the old validate_chain_address_format() loop from the pre-auth position |
N/A (removed code) |
Changes — tests/test_bridge_lock_ledger.py
| Line | Change | Assessment |
|---|---|---|
| +1 | Changed the unit-test input for test_valid_rustchain_address from "RTC_test123abc" (invalid hex) to "RTC" + "a" * 40 (valid canonical wallet address) |
Correct. This test exercises validate_chain_address_format() directly — the strict wallet-address validator — so it should use a valid wallet-address fixture. The old fixture (RTC_test123abc) contained non-hex characters (t, _) and was never a valid wallet address, making the test misleading about what it was actually checking. |
Remaining notes
-
validate_miner_id_format()fallback — The import at the top ofbridge_api.pyuses a try/except ImportError fallback that definesvalidate_miner_id_format()to accept IDs >=3 chars starting with"RTC". If the productionrustchain_v2_integrated_v2_2_1_rip200module defines different validation rules, production vs. standalone-test behavior could diverge. Worth confirming the production module's criteria match the fallback assumptions. -
No test for auth-before-validation ordering — There is no test asserting that an unauthenticated deposit with an invalid-format miner ID returns
401/503before any address-validation error. The existingTestBridgeInitiateAuthclass tests auth rejection but uses the default test miner ID. A targeted test case with a short/invalid miner ID and no admin key would guard against regression of the auth-masking bug.
Verdict
Approve. The two bugs are real, the fix is surgical and correct, the auth ordering change is a clear improvement, and the test-fixture correction eliminates a misleading assertion. The notes above are minor observations, not blockers.
Summary
Refs #305.
Fixes a bridge-initiate regression where deposit requests treated the RustChain
source_addressas a strictRTC+ 40-hex wallet address before checking operator authorization. Deposit locks are keyed bybalances.miner_id, so valid miner IDs such asRTC_test_minerwere rejected with400and unauthenticated requests were masked as validation errors instead of returning401/503.Changes:
validate_miner_id_format()only for the RustChain deposit source miner ID.validate_chain_address_format("rustchain", ...)strict for canonicalRTC+ 40-hex wallet/address checks and all non-deposit route address validation.Validation
Focused passing checks:
.venv/bin/python -m pytest node/test_bridge_address_validation_6193_6195.py tests/test_bridge_lock_ledger.py::TestAddressValidation tests/test_bridge_lock_ledger.py::TestBridgeInitiateAuth -q->42 passedBroader bridge-file check:
.venv/bin/python -m pytest tests/test_bridge_lock_ledger.py -q->58 passed, 4 failedlock_ledgerread-route admin-auth expectations. I did not change those routes becausenode/lock_ledger.pyexplicitly documents that they expose miner lock balances / pending unlocks and require an admin key.No private keys, wallet secrets, production mutation, proxy/profile changes, or payout operations were used.