From a3d996c1f500c5f0ee1a05db2692f2b5fb736f53 Mon Sep 17 00:00:00 2001 From: crowniteto Date: Tue, 26 May 2026 13:41:35 +0000 Subject: [PATCH] fix(gpu): verify provider balance credit on escrow release (#6161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, gpu_release() executed an UPDATE on the balances table without checking rowcount. If the provider (to_wallet) had no existing balances row, the UPDATE matched 0 rows but the escrow was still marked as 'released' — funds debited from payer but never credited to provider. Now we check credited.rowcount: if 0 (provider has no balances row), we INSERT a new row with the credited amount instead of silently dropping the funds. Fixes #6161 --- node/gpu_render_endpoints.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/node/gpu_render_endpoints.py b/node/gpu_render_endpoints.py index 61fb39fae..65e65562d 100644 --- a/node/gpu_render_endpoints.py +++ b/node/gpu_render_endpoints.py @@ -225,10 +225,19 @@ def gpu_release(): db.rollback() return jsonify({"error": "Job was already processed"}), 409 - # Transfer to provider - db.execute("UPDATE balances SET balance_rtc = balance_rtc + ? WHERE miner_pk = ?", (job["amount_rtc"], job["to_wallet"])) - db.commit() - return jsonify({"ok": True, "status": "released"}) + # Transfer to provider — verify the provider has a balances row + credited = db.execute( + "UPDATE balances SET balance_rtc = balance_rtc + ? WHERE miner_pk = ?", + (job["amount_rtc"], job["to_wallet"]), + ) + if credited.rowcount != 1: + # Provider has no balances row — create one before crediting + db.execute( + "INSERT INTO balances (miner_pk, balance_rtc) VALUES (?, ?)", + (job["to_wallet"], job["amount_rtc"]), + ) + db.commit() + return jsonify({"ok": True, "status": "released"}) except sqlite3.Error as e: return jsonify({"error": str(e)}), 500 finally: