UTXO↔account dual-write writes 1000x incorrect balance units
Summary
When UTXO_DUAL_WRITE=1 is enabled, the /utxo/transfer endpoint writes amount_rtc * 1_000_000_000 (9 decimals) into balances.amount_i64, but every other writer and reader in the account model uses amount_rtc * 1_000_000 (6 decimals). This causes recipient balances to be 1000x larger than they should be.
Additionally, the /utxo/integrity endpoint compares UTXO totals (stored at 8 decimals / nanoRTC) against raw SUM(amount_i64) from the account model (stored at 6 decimals / micro-RTC) without any unit conversion, so it can never detect this mismatch.
Affected Files
node/utxo_endpoints.py — line 320 (dual-write multiplier), lines 133-155 (integrity endpoint)
Root Cause
Two independent unit mismatches in the UTXO↔account dual-write bridge:
1. Dual-write multiplier (line 320):
# BUG: writes 9 decimals, but account model expects 6
amount_i64 = int(amount_rtc * 1_000_000_000) # 9 decimals
The account model (rustchain_v2_integrated_v2.2.1_rip200.py line 2370, 5737, 4973, etc.) consistently uses * 1_000_000 (6 decimals) for amount_i64. The dual-write path uses * 1_000_000_000 (9 decimals) — a 1000x over-credit.
2. Integrity endpoint unit comparison (lines 133-155):
# BUG: compares nanoRTC (8 decimals) against raw amount_i64 (6 decimals)
account_total = SUM(amount_i64) # 6-decimal uRTC
result = integrity_check(expected_total=account_total) # expects nanoRTC
result['account_total_rtc'] = account_total / UNIT # UNIT = 100_000_000 (8 dec)
The integrity check passes SUM(amount_i64) directly to integrity_check(expected_total=...) which compares it against the UTXO total in nanoRTC (8 decimals). These are different units, so the comparison is meaningless.
Impact
When dual-write is enabled (UTXO_DUAL_WRITE=1):
- A transfer of 10 RTC credits the recipient with 10,000 RTC in the account model (1000x)
- A transfer of 0.001 RTC credits 1 RTC instead of 0.001 RTC
- The
/utxo/integrity endpoint cannot detect this corruption because it compares incompatible units
- Ledger
delta_i64 entries are also 1000x inflated
The UTXO model itself is unaffected — utxo_boxes.value_nrtc uses the correct 8-decimal UNIT = 100_000_000. Only the shadow account-model writes are corrupted.
Reproduction
- Start the node with
UTXO_DUAL_WRITE=1
- Seed a UTXO balance for
RTC_test_sender
- POST
/utxo/transfer with amount_rtc: 10.0 from sender to recipient
- Query
SELECT amount_i64 FROM balances WHERE miner_id = 'RTC_test_recipient'
- Expected:
10_000_000 (10 × 1,000,000). Actual (bug): 10_000_000_000 (10 × 1,000,000,000)
Distinction from Prior Findings
This finding is specific to the dual-write bridge between UTXO and account models — a unit conversion error that corrupts account-model balances by 1000x.
Fix
Change the dual-write multiplier from 1_000_000_000 to 1_000_000 (ACCOUNT_UNIT), and fix the integrity endpoint to convert account totals from 6-decimal to 8-decimal units before comparison.
Payout wallet: RTC1d48d848a5aa5ecf2c5f01aa5fb64837daaf2f35
UTXO↔account dual-write writes 1000x incorrect balance units
Summary
When
UTXO_DUAL_WRITE=1is enabled, the/utxo/transferendpoint writesamount_rtc * 1_000_000_000(9 decimals) intobalances.amount_i64, but every other writer and reader in the account model usesamount_rtc * 1_000_000(6 decimals). This causes recipient balances to be 1000x larger than they should be.Additionally, the
/utxo/integrityendpoint compares UTXO totals (stored at 8 decimals / nanoRTC) against rawSUM(amount_i64)from the account model (stored at 6 decimals / micro-RTC) without any unit conversion, so it can never detect this mismatch.Affected Files
node/utxo_endpoints.py— line 320 (dual-write multiplier), lines 133-155 (integrity endpoint)Root Cause
Two independent unit mismatches in the UTXO↔account dual-write bridge:
1. Dual-write multiplier (line 320):
The account model (
rustchain_v2_integrated_v2.2.1_rip200.pyline 2370, 5737, 4973, etc.) consistently uses* 1_000_000(6 decimals) foramount_i64. The dual-write path uses* 1_000_000_000(9 decimals) — a 1000x over-credit.2. Integrity endpoint unit comparison (lines 133-155):
The integrity check passes
SUM(amount_i64)directly tointegrity_check(expected_total=...)which compares it against the UTXO total in nanoRTC (8 decimals). These are different units, so the comparison is meaningless.Impact
When dual-write is enabled (
UTXO_DUAL_WRITE=1):/utxo/integrityendpoint cannot detect this corruption because it compares incompatible unitsdelta_i64entries are also 1000x inflatedThe UTXO model itself is unaffected —
utxo_boxes.value_nrtcuses the correct 8-decimalUNIT = 100_000_000. Only the shadow account-model writes are corrupted.Reproduction
UTXO_DUAL_WRITE=1RTC_test_sender/utxo/transferwithamount_rtc: 10.0from sender to recipientSELECT amount_i64 FROM balances WHERE miner_id = 'RTC_test_recipient'10_000_000(10 × 1,000,000). Actual (bug):10_000_000_000(10 × 1,000,000,000)Distinction from Prior Findings
This finding is specific to the dual-write bridge between UTXO and account models — a unit conversion error that corrupts account-model balances by 1000x.
Fix
Change the dual-write multiplier from
1_000_000_000to1_000_000(ACCOUNT_UNIT), and fix the integrity endpoint to convert account totals from 6-decimal to 8-decimal units before comparison.Payout wallet:
RTC1d48d848a5aa5ecf2c5f01aa5fb64837daaf2f35