From 0476b8c1ea10dc1e702c082db3c3255940aaace6 Mon Sep 17 00:00:00 2001 From: Teemu Patja Date: Fri, 15 Sep 2017 10:24:55 +0300 Subject: [PATCH] Fault tolerance for payout confirmal * if a payout transaction sent by repo admin from cljs does not get mined within 3 hours, consider it as failed and re-enable confirm button Fixes: #94 --- resources/sql/queries.sql | 10 ++++++- src/clj/commiteth/db/bounties.clj | 5 ++++ src/clj/commiteth/scheduler.clj | 49 ++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql index e282898..e5ef288 100644 --- a/resources/sql/queries.sql +++ b/resources/sql/queries.sql @@ -295,7 +295,8 @@ SELECT u.address AS payout_address, u.login AS payee_login, i.confirm_hash AS confirm_hash, - i.payout_hash AS payout_hash + i.payout_hash AS payout_hash, + i.updated AS updated FROM issues i, pull_requests p, users u, repositories r WHERE p.issue_id = i.issue_id @@ -326,6 +327,13 @@ SET payout_hash = :payout_hash, updated = timezone('utc'::text, now()) WHERE issue_id = :issue_id; +-- :name reset-payout-hash :! :n +-- :doc sets issue's payout transaction hash to NULL +UPDATE issues +SET payout_hash = NULL +WHERE issue_id = :issue_id; + + -- :name update-payout-receipt :! :n -- :doc updates issue with payout transaction receipt UPDATE issues diff --git a/src/clj/commiteth/db/bounties.clj b/src/clj/commiteth/db/bounties.clj index 04d6e3d..bda501b 100644 --- a/src/clj/commiteth/db/bounties.clj +++ b/src/clj/commiteth/db/bounties.clj @@ -55,6 +55,11 @@ (jdbc/with-db-connection [con-db *db*] (db/update-payout-hash con-db {:issue_id issue-id :payout_hash payout-hash}))) +(defn reset-payout-hash + [issue-id] + (jdbc/with-db-connection [con-db *db*] + (db/reset-payout-hash con-db {:issue_id issue-id}))) + (defn update-payout-receipt [issue-id payout-receipt] (jdbc/with-db-connection [con-db *db*] diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index f58049c..10b85b3 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -11,6 +11,7 @@ [clojure.tools.logging :as log] [mount.core :as mount] [clj-time.core :as t] + [clj-time.coerce :as time-coerce] [clj-time.periodic :refer [periodic-seq]] [chime :refer [chime-at]])) @@ -116,6 +117,15 @@ (log/info "confirm hash:" confirm-hash) (db-bounties/update-confirm-hash issue-id confirm-hash))))) + +(defn older-than-3h? + [timestamp] + (let [now (t/now) + ts (time-coerce/from-date timestamp) + diff (t/in-hours (t/interval ts now))] + (println "hour diff:" diff) + (> diff 3))) + (defn update-payout-receipt "Gets transaction receipt for each confirmed payout and updates payout_hash" [] @@ -129,30 +139,35 @@ balance-eth :balance_eth tokens :tokens confirm-id :confirm-hash - payee-login :payee_login} (db-bounties/confirmed-payouts)] + payee-login :payee_login + updated :updated} (db-bounties/confirmed-payouts)] (log/debug "confirmed payout:" payout-hash) - (when-let [receipt (eth/get-transaction-receipt payout-hash)] + (if-let [receipt (eth/get-transaction-receipt payout-hash)] (let [tokens (multisig/token-balances contract-address) eth-balance (eth/get-balance-wei contract-address)] (if (or (some #(> (second %) 0.0) tokens) (> eth-balance 0)) - (log/info "Contract still has funds") - (when (multisig/is-confirmed? contract-address confirm-id) - (log/info "Detected bounty with funds and confirmed payout, calling executeTransaction") - (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] - (log/info "execute tx:" execute-tx-hash)))) + (do + (log/info "Contract still has funds") + (when (multisig/is-confirmed? contract-address confirm-id) + (log/info "Detected bounty with funds and confirmed payout, calling executeTransaction") + (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] + (log/info "execute tx:" execute-tx-hash)))) - (do - (log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt) - (db-bounties/update-payout-receipt issue-id receipt) - (github/update-paid-issue-comment owner - repo - comment-id - contract-address - (eth-decimal->str balance-eth) - tokens - payee-login)))))) + (do + (log/info "Payout has succeeded, saving payout receipt for issue #" issue-id ": " receipt) + (db-bounties/update-payout-receipt issue-id receipt) + (github/update-paid-issue-comment owner + repo + comment-id + contract-address + (eth-decimal->str balance-eth) + tokens + payee-login)))) + (when (older-than-3h? updated) + (log/info "Resetting payout hash for issue" issue-id "as it has not been mined in 3h") + (db-bounties/reset-payout-hash issue-id))))) (defn abs "(abs n) is the absolute value of n"