Three Presses, Three Remittances — Python Bug Hunt
Modelled on the "Dalmellington bug" in the Post Office's Horizon system, one of the defects examined in the High Court's 2019 Horizon Issues judgment (Bates…
- Language: Python
- Layer: Database
- Difficulty: Medium
- Concepts: Idempotency, Money
- Modelled on: Post Office Horizon · Dalmellington
- Visible tests: a single remittance is recorded; pressing confirm three times books one remittance
- Reward: 50 XP for a complete fix
Briefing
Modelled on the "Dalmellington bug" in the Post Office's Horizon system, one of the defects examined in the High Court's 2019 Horizon Issues judgment (Bates v Post Office). At the Dalmellington branch a cash remittance to an outreach branch was recorded several times: the terminal was slow to respond, the confirm button was pressed again, and each press was booked as another transfer. The duplicated entries appeared as a cash shortfall at the branch. Across the wider Horizon scandal, hundreds of subpostmasters were held liable — many prosecuted — for shortfalls the system produced.
remittance.py books a remittance. The counter terminal sends one call per press of the confirm button, each carrying the request_key generated when the remittance screen was opened.
Make record_remittance idempotent on that key.
Bug report
BUG-HNG-DAL · Priority: Critical (branch accounts) · Reported by: branch support
record_remittance(ledger, branch, request_key, amount_pence):
- amount_pence <= 0 raises ValueError (unchanged)
- the first call for a (branch, request_key) inserts one row and returns {"status": "recorded", "id": <row id>}
- a repeat call with the same branch, key and amount inserts nothing and returns {"status": "duplicate", "id": <the original row id>}
- a repeat with the same branch and key but a DIFFERENT amount raises ValueError and inserts nothing
- keys are scoped to a branch: the same key at another branch is a separate remittance
Observed: a remittance confirmed three times while the terminal hung is booked three times; the branch shows a shortfall of twice the amount.
Logs
[horizon] branch=DAL rem_out key=R-5510 amount=800000 row=41
[horizon] branch=DAL rem_out key=R-5510 amount=800000 row=42
[horizon] branch=DAL rem_out key=R-5510 amount=800000 row=43
[balancing] branch=DAL discrepancy=-1600000The code as shipped
src/branch/remittance.py (editable)
# Books a cash remittance sent from a branch.
def record_remittance(ledger, branch, request_key, amount_pence):
if amount_pence <= 0:
raise ValueError("amount must be positive")
row = ledger.insert(branch, request_key, amount_pence)
return {"status": "recorded", "id": row["id"]}
Read-only context: src/branch/ledger.py.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Python bug hunts.