From d9bb04036d8fc72c5b1edfe771e73436d0af98ec Mon Sep 17 00:00:00 2001 From: Rob Culliton Date: Tue, 1 May 2018 20:26:45 -0400 Subject: [PATCH 01/68] single click bounty revocation --- README.md | 4 +- contracts/README.md | 4 +- contracts/build.sh | 12 +- ...251-update-issue-execution-posted.down.sql | 1 + ...53251-update-issue-execution-posted.up.sql | 1 + resources/sql/queries.sql | 53 +++++++- src/clj/commiteth/db/bounties.clj | 10 ++ src/clj/commiteth/db/issues.clj | 16 +++ src/clj/commiteth/db/pull_requests.clj | 4 +- src/clj/commiteth/eth/core.clj | 14 ++ src/clj/commiteth/routes/services.clj | 69 ++++++++-- src/clj/commiteth/scheduler.clj | 128 ++++++++++++------ src/cljs/commiteth/handlers.cljs | 42 +++++- src/cljs/commiteth/manage_payouts.cljs | 20 ++- 14 files changed, 311 insertions(+), 67 deletions(-) create mode 100644 resources/migrations/20180426153251-update-issue-execution-posted.down.sql create mode 100644 resources/migrations/20180426153251-update-issue-execution-posted.up.sql diff --git a/README.md b/README.md index b0a12dd..c7260b9 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,9 @@ lein less auto ``` ### Solidity compilation -Invoke `build-contracts` Leiningen task to compile Solidity files into Java classes: +Compile Solidity files into Java classes with: ``` -lein build-contracts +cd contracts && ./build.sh ``` ### Clojure app without REPL diff --git a/contracts/README.md b/contracts/README.md index f92dc0e..59015c9 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -2,8 +2,8 @@ This directory contains all the underlying smart contracts used by the OpenBounty platform. -- A script `contracts/build.sh` is part of this repository and can be used to -compile the contracts and copy Java interfaces into `src/java/`. +-- A script `build.sh` is part of this directory and can be used to +-compile the contracts and copy Java interfaces into `src/java/`. In order to run the script the following dependencies have to be met: diff --git a/contracts/build.sh b/contracts/build.sh index 7b00d8c..99e4991 100755 --- a/contracts/build.sh +++ b/contracts/build.sh @@ -1,12 +1,18 @@ #!/bin/bash -eu -SOLC=$(which solc) -WEB3J=$(which web3j) +function print_dependency_message +{ + echo "error: " $1 "must already be installed!" +} + +SOLC=$(which solc) || print_dependency_message "solc" + +WEB3J=$(which web3j) || print_dependency_message "web3" rm -f resources/contracts/*.{abi,bin} # compile contracts -for f in contracts/{TokenReg,MultiSigTokenWallet*}.sol; do +for f in {TokenReg,MultiSigTokenWallet*}.sol; do $SOLC $f --overwrite --bin --abi --optimize -o resources/contracts done diff --git a/resources/migrations/20180426153251-update-issue-execution-posted.down.sql b/resources/migrations/20180426153251-update-issue-execution-posted.down.sql new file mode 100644 index 0000000..99410a6 --- /dev/null +++ b/resources/migrations/20180426153251-update-issue-execution-posted.down.sql @@ -0,0 +1 @@ +ALTER TABLE "public"."issues" DROP COLUMN "execute_posted"; diff --git a/resources/migrations/20180426153251-update-issue-execution-posted.up.sql b/resources/migrations/20180426153251-update-issue-execution-posted.up.sql new file mode 100644 index 0000000..2e4dd32 --- /dev/null +++ b/resources/migrations/20180426153251-update-issue-execution-posted.up.sql @@ -0,0 +1 @@ +ALTER TABLE "public"."issues" ADD COLUMN "execute_posted" boolean; diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql index 0f46d62..35bca09 100644 --- a/resources/sql/queries.sql +++ b/resources/sql/queries.sql @@ -73,7 +73,6 @@ FROM repositories WHERE owner = :owner AND repo = :repo; - -- :name create-repository! :str]] [crypto.random :as random] [clojure.set :refer [rename-keys]] - [clojure.string :as str])) + [clojure.string :as str] + [commiteth.eth.multisig-wallet :as multisig] + [commiteth.db.bounties :as db-bounties] + [commiteth.scheduler :as scheduler] + [clj-time.core :as t] + [clj-time.periodic :refer [periodic-seq]])) (defn add-bounties-for-existing-issues? [] (env :add-bounties-for-existing-issues false)) @@ -155,13 +162,38 @@ (let [whitelist (env :user-whitelist #{})] (whitelist user))) +(defn execute-revocation [issue-id contract-address payout-address] + (log/info (str "executing revocation for " issue-id "at" contract-address)) + (let [execute-hash (multisig/send-all {:contract contract-address + :payout-address payout-address + :internal-tx-id (str "payout-github-issue-" issue-id)}) + execute-write (db-bounties/update-execute-hash issue-id execute-hash)] + {:execute-hash execute-hash + :execute-write execute-write})) + +(defn update-confirm-hash + [issue-id execute-hash] + (log/infof "issue %s: pending payout: %s" issue-id execute-hash) + (try + (when-let [receipt (eth/get-transaction-receipt execute-hash)] + (log/infof "issue %s: execution receipt for issue " issue-id receipt) + (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] + (log/infof "issue %s: confirm hash:" issue-id confirm-hash) + (db-bounties/update-confirm-hash issue-id confirm-hash) + {:confirm_hash confirm-hash})) + (catch Throwable ex + (log/errorf ex "issue %s: update-confirm-hash exception:" issue-id)))) + (defapi service-routes (when (:dev env) - {:swagger {:ui "/swagger-ui" - :spec "/swagger.json" - :data {:info {:version "0.1" - :title "commitETH API" - :description "commitETH API"}}}}) + {:swagger {:ui "/swagger-ui" + :spec "/swagger.json" + :data {:info {:version "0.1" + :title "commitETH API" + :description "commitETH API"}}} + :exceptions {:handlers + {::ex/request-parsing (ex/with-logging ex/request-parsing-handler :info) + ::ex/response-validation (ex/with-logging ex/response-validation-handler :error)}}}) (context "/api" [] (GET "/top-hunters" [] @@ -191,11 +223,11 @@ (POST "/" [] :auth-rules authenticated? :current-user user - :body [body {:address s/Str + :body [body {:address s/Str :is_hidden_in_hunters s/Bool}] :summary "Updates user's fields." - (let [user-id (:id user) + (let [user-id (:id user) {:keys [address]} body] (when-not (eth/valid-address? address) @@ -226,9 +258,9 @@ (log/debug "/bounty/X/payout" params) (let [{issue :issue payout-hash :payout-hash} params - result (bounties-db/update-payout-hash - (Integer/parseInt issue) - payout-hash)] + result (bounties-db/update-payout-hash + (Integer/parseInt issue) + payout-hash)] (log/debug "result" result) (if (= 1 result) (ok) @@ -237,4 +269,17 @@ :auth-rules authenticated? :current-user user (log/debug "/user/bounties") - (ok (user-bounties user)))))) + (ok (user-bounties user))) + (POST "/revoke" {{issue-id :issue-id + contract-address :contract-address + owner-address :owner-address} :params} + :auth-rules authenticated? + :current-user user + (do (log/infof "calling revoke-initiate for %s with %s %s" issue-id contract-address owner-address) + (if-let [{:keys [execute-hash execute-write]} (execute-revocation issue-id contract-address owner-address)] + (if (scheduler/poll-transaction-logs execute-hash contract-address) + (if-let [{confirm-hash :confirm_hash} (update-confirm-hash issue-id execute-hash)] + (ok {:confirm-hash confirm-hash}) + (bad-request "The confirm hash could not be updated")) + (bad-request "The transaction hash could not be confirmed in a reasonable amount of time")) + (bad-request (str "We were unable to withdraw everything from " contract-address)))))))) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 57aa61e..aefff23 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -149,25 +149,6 @@ (log/error ex "issue %s: self-sign-bounty exception" issue-id))))) (log/info "Exit self-sign-bounty")) -(defn update-confirm-hash - "Gets transaction receipt for each pending payout and updates DB confirm_hash with tranaction ID of commiteth bot account's confirmation." - [] - (log/info "In update-confirm-hash") - (p :update-confirm-hash - (doseq [{issue-id :issue_id - execute-hash :execute_hash} (db-bounties/pending-payouts)] - (log/infof "issue %s: pending payout: %s" issue-id execute-hash) - (try - (when-let [receipt (eth/get-transaction-receipt execute-hash)] - (log/infof "issue %s: execution receipt for issue " issue-id receipt) - (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] - (log/infof "issue %s: confirm hash:" issue-id confirm-hash) - (db-bounties/update-confirm-hash issue-id confirm-hash))) - (catch Throwable ex - (log/errorf ex "issue %s: update-confirm-hash exception:" issue-id))))) - (log/info "Exit update-confirm-hash")) - - (defn update-watch-hash "Sets watch-hash to NULL for bounties where watch tx has been mined. Used to avoid unneeded watch transactions in update-bounty-token-balances" [] @@ -190,24 +171,8 @@ (println "hour diff:" diff) (> diff 3))) -(defn update-payout-receipt - "Gets transaction receipt for each confirmed payout and updates payout_hash" - [] - (log/info "In update-payout-receipt") - (p :update-payout-receipt - (doseq [{issue-id :issue_id - payout-hash :payout_hash - contract-address :contract_address - repo :repo - owner :owner - comment-id :comment_id - issue-number :issue_number - balance-eth :balance_eth - tokens :tokens - confirm-id :confirm_hash - payee-login :payee_login - updated :updated} (db-bounties/confirmed-payouts)] - (log/infof "issue %s: confirmed payout: %s" issue-id payout-hash) +(defn update-payout-receipt [owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated] + (log/infof "issue %s: confirmed payout: %s" issue-id payout-hash) (try (if-let [receipt (eth/get-transaction-receipt payout-hash)] (let [contract-tokens (multisig/token-balances contract-address) @@ -217,9 +182,9 @@ (> contract-eth-balance 0)) (do (log/infof "issue %s: Contract (%s) still has funds" issue-id contract-address) - (when (multisig/is-confirmed? contract-address confirm-id) + (when (multisig/is-confirmed? contract-address confirm-hash) (log/infof "issue %s: Detected bounty with funds and confirmed payout, calling executeTransaction" issue-id) - (let [execute-tx-hash (multisig/execute-tx contract-address confirm-id)] + (let [execute-tx-hash (multisig/execute-tx contract-address confirm-hash)] (log/infof "issue %s: execute tx: %s" issue-id execute-tx-hash)))) (do @@ -236,8 +201,47 @@ (log/warn "issue %s: Resetting payout hash for issue as it has not been mined in 3h" issue-id) (db-bounties/reset-payout-hash issue-id))) (catch Throwable ex - (log/error ex "issue %s: update-payout-receipt exception" issue-id))))) - (log/info "Exit update-payout-receipt")) + (log/error ex "issue %s: update-payout-receipt exception" issue-id)))) + +(defn update-revoked-payout-receipts + "Gets transaction receipt for each confirmed revocation and updates payout_hash" + [] + (log/info "In update-revoked-payout-receipts") + (p :update-payout-receipts + (doseq [{issue-id :issue_id + payout-hash :payout_hash + contract-address :contract_address + repo :repo + owner :owner + comment-id :comment_id + issue-number :issue_number + balance-eth :balance_eth + tokens :tokens + confirm-hash :confirm_hash + payee-login :payee_login + updated :updated} (db-bounties/confirmed-revocation-payouts)] + (update-payout-receipt owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated))) + (log/info "Exit update-revoked-payout-receipts")) + +(defn update-payout-receipts + "Gets transaction receipt for each confirmed payout and updates payout_hash" + [] + (log/info "In update-payout-receipts") + (p :update-payout-receipts + (doseq [{issue-id :issue_id + payout-hash :payout_hash + contract-address :contract_address + repo :repo + owner :owner + comment-id :comment_id + issue-number :issue_number + balance-eth :balance_eth + tokens :tokens + confirm-hash :confirm_hash + payee-login :payee_login + updated :updated} (db-bounties/confirmed-payouts)] + (update-payout-receipt owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated))) + (log/info "Exit update-payout-receipts")) (defn abs "(abs n) is the absolute value of n" @@ -396,8 +400,8 @@ (run-tasks [deploy-pending-contracts update-issue-contract-address - update-confirm-hash - update-payout-receipt + update-payout-receipts + update-revoked-payout-receipts update-watch-hash self-sign-bounty ]) @@ -436,3 +440,41 @@ :stop (do (log/info "stopping scheduler") (scheduler))) + +(defn contract-confirmation-logs [contract-address] + "retrives all log events for the confirmation topic since contract creation" + (some-> contract-address + issues/get-issue-by-contract-address + :transaction_hash + eth/get-transaction-by-hash + :blockNumber + (eth/get-logs contract-address [(:confirmation multisig/topics)]))) + +(defn hash-in-logs? + "return true if the transaction hash is present in the queryable blockchain" + [hash logs] + (some #(= hash (:transactionHash %)) logs)) + +(defn execution-status [execute-hash contract-address] + "check to see if a given execute-hash has been confirmed" + (log/infof "checking contract for logs containing %s" execute-hash) + (let [logs (contract-confirmation-logs contract-address)] + (hash-in-logs? execute-hash logs))) + + +(defn poll-transaction-logs [execute-hash contract-address] + "check for execution hash in logs for a few minutes" + (let [found? (promise) + intervals (take 6 + (periodic-seq (t/now) + (t/seconds 30)))] + ;; polling will be slow but if we want to move to an event driven + ;; model then we can listen for events, rather than logs, once we're + ;; using a geth node again + (chime-at intervals + (fn [time] + (when (execution-status execute-hash contract-address) + (deliver found? true))) + {:on-finished (fn [] + (deliver found? false))}) + @found?)) diff --git a/src/cljs/commiteth/handlers.cljs b/src/cljs/commiteth/handlers.cljs index 63b3fda..4f43b0d 100644 --- a/src/cljs/commiteth/handlers.cljs +++ b/src/cljs/commiteth/handlers.cljs @@ -1,6 +1,7 @@ (ns commiteth.handlers (:require [commiteth.db :as db] - [re-frame.core :refer [dispatch + [re-frame.core :refer [debug + dispatch reg-event-db reg-event-fx reg-fx @@ -20,6 +21,9 @@ (rf-storage/reg-co-fx! :commiteth-sob {:fx :store :cofx :store}) +;; https://github.com/Day8/re-frame/blob/master/docs/Debugging-Event-Handlers.md +(def interceptors [(when ^boolean goog.DEBUG debug)]) + (reg-fx :http (fn [{:keys [method url on-success on-error finally params]}] @@ -64,6 +68,7 @@ (reg-event-fx :initialize-web3 + interceptors (fn [{:keys [db]} [_]] (let [injected-web3 (common/web3) w3 (when (boolean injected-web3) @@ -209,6 +214,7 @@ (reg-event-fx :load-owner-bounties + interceptors (fn [{:keys [db]} [_]] {:db (assoc db :owner-bounties-loading? true) :http {:method GET @@ -376,6 +382,7 @@ (reg-event-fx :save-payout-hash + interceptors (fn [{:keys [db]} [_ issue-id payout-hash]] {:db db :http {:method POST @@ -405,8 +412,40 @@ (defn strip-0x [x] (str/replace x #"^0x" "")) +(reg-event-fx + :revoke-bounty-success + interceptors + (fn [{:keys [db]} [_ {:keys [issue-id owner-address contract-address confirm-hash]}]] + {:dispatch [:confirm-payout {:issue_id issue-id + :owner_address owner-address + :contract_address contract-address + :confirm_hash confirm-hash}]})) + +(reg-event-fx + :revoke-bounty-error + interceptors + (fn [{:keys [db]} [_ issue-id response]] + {:dispatch [:set-flash-message + :error (if (= 400 (:status response)) + (:response response) + (str "Failed to initiate revocation for: " issue-id + (:status-text response)))]})) + +(reg-event-fx + :revoke-bounty + interceptors + (fn [{:keys [db]} [_ fields]] + (let [issue-id (:issue_id fields)] + {:http {:method POST + :url "/api/user/revoke" + ;; merge returned confirm hash with + :on-success #(dispatch [:revoke-bounty-success (merge fields %)]) + :on-error #(dispatch [:revoke-bounty-error issue-id %]) + :params fields}}))) + (reg-event-fx :confirm-payout + interceptors (fn [{:keys [db]} [_ {issue-id :issue_id owner-address :owner_address contract-address :contract_address @@ -437,6 +476,7 @@ (reg-event-fx :payout-confirmed + interceptors (fn [{:keys [db]} [_ issue-id]] {:dispatch [:load-owner-bounties] :db (-> db diff --git a/src/cljs/commiteth/manage_payouts.cljs b/src/cljs/commiteth/manage_payouts.cljs index c2f0f44..f730cba 100644 --- a/src/cljs/commiteth/manage_payouts.cljs +++ b/src/cljs/commiteth/manage_payouts.cljs @@ -6,6 +6,7 @@ [commiteth.routes :as routes] [commiteth.model.bounty :as bnt] [commiteth.ui.balances :as ui-balances] + [commiteth.config :as config] [commiteth.common :as common :refer [human-time]])) (defn pr-url [{owner :repo_owner @@ -13,6 +14,12 @@ repo :repo_name}] (str "https://github.com/" owner "/" repo "/pull/" pr-number)) +;; TODO put this in cljc file +(defn etherscan-tx-url [tx-id] + (str "https://" + (when (config/on-testnet?) "ropsten.") + "etherscan.io/tx/" tx-id)) + (def primary-button-button :button.f7.ttu.tracked.outline-0.bg-sob-blue.white.pv3.ph4.pg-med.br3.bn.pointer.shadow-7) (def primary-button-link :a.dib.tc.f7.ttu.tracked.bg-sob-blue.white.pv2.ph3.pg-med.br2.pointer.hover-white.shadow-7) @@ -57,6 +64,15 @@ "Signed off" "Confirm Payment")]))) +(defn revoke-button [{issue-id :issue-id + contract-address :contract_address + owner-address :owner_address}] + [:button.ui.button + {:on-click #(rf/dispatch [:revoke-bounty {:contract-address contract-address + :issue-id issue-id + :owner-address owner-address}])} + "Revoke"]) + (defn confirm-row [bounty claim] (let [payout-address-available? (:payout_address bounty)] [:div @@ -236,10 +252,12 @@ [:div [ui-balances/usd-value-label (:value-usd bounty)]]]) -(defn unclaimed-bounty [bounty] +(defn unclaimed-bounty [{value-usd :value-usd :as bounty}] [:div.w-third-l.fl-l.pa2 [square-card [bounty-title-link bounty {:show-date? true :max-length 60}] + (when (> value-usd 0) + [revoke-button bounty]) [small-card-balances bounty]]]) (defn paid-bounty [bounty] From cec0718b1ec2b698f9f0ac683730ef9ace34dc96 Mon Sep 17 00:00:00 2001 From: Rob Culliton Date: Tue, 1 May 2018 21:53:02 -0400 Subject: [PATCH 02/68] move update-confirm-hash back to scheduler, make sure job is in 1-min tasks --- src/clj/commiteth/routes/services.clj | 14 +--- src/clj/commiteth/scheduler.clj | 99 +++++++++++++++++---------- 2 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 3808e2d..9f37dcc 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -171,18 +171,6 @@ {:execute-hash execute-hash :execute-write execute-write})) -(defn update-confirm-hash - [issue-id execute-hash] - (log/infof "issue %s: pending payout: %s" issue-id execute-hash) - (try - (when-let [receipt (eth/get-transaction-receipt execute-hash)] - (log/infof "issue %s: execution receipt for issue " issue-id receipt) - (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] - (log/infof "issue %s: confirm hash:" issue-id confirm-hash) - (db-bounties/update-confirm-hash issue-id confirm-hash) - {:confirm_hash confirm-hash})) - (catch Throwable ex - (log/errorf ex "issue %s: update-confirm-hash exception:" issue-id)))) (defapi service-routes (when (:dev env) @@ -278,7 +266,7 @@ (do (log/infof "calling revoke-initiate for %s with %s %s" issue-id contract-address owner-address) (if-let [{:keys [execute-hash execute-write]} (execute-revocation issue-id contract-address owner-address)] (if (scheduler/poll-transaction-logs execute-hash contract-address) - (if-let [{confirm-hash :confirm_hash} (update-confirm-hash issue-id execute-hash)] + (if-let [{confirm-hash :confirm_hash} (scheduler/update-confirm-hash issue-id execute-hash)] (ok {:confirm-hash confirm-hash}) (bad-request "The confirm hash could not be updated")) (bad-request "The transaction hash could not be confirmed in a reasonable amount of time")) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index aefff23..27706a9 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -149,6 +149,30 @@ (log/error ex "issue %s: self-sign-bounty exception" issue-id))))) (log/info "Exit self-sign-bounty")) +(defn update-confirm-hash + [issue-id execute-hash] + (log/infof "issue %s: pending payout: %s" issue-id execute-hash) + (try + (when-let [receipt (eth/get-transaction-receipt execute-hash)] + (log/infof "issue %s: execution receipt for issue " issue-id receipt) + (when-let [confirm-hash (multisig/find-confirmation-tx-id receipt)] + (log/infof "issue %s: confirm hash:" issue-id confirm-hash) + (db-bounties/update-confirm-hash issue-id confirm-hash) + {:confirm_hash confirm-hash})) + (catch Throwable ex + (log/errorf ex "issue %s: update-confirm-hash exception:" issue-id)))) + +(defn update-confirm-hashes + "Gets transaction receipt for each pending payout and updates DB confirm_hash with tranaction ID of commiteth bot account's confirmation." + [] + (log/info "In update-confirm-hashes") + (p :update-confirm-hash + (doseq [{issue-id :issue_id + execute-hash :execute_hash} (db-bounties/pending-payouts)] + + (update-confirm-hash issue-id execute-hash))) + (log/info "Exit update-confirm-hash")) + (defn update-watch-hash "Sets watch-hash to NULL for bounties where watch tx has been mined. Used to avoid unneeded watch transactions in update-bounty-token-balances" [] @@ -252,6 +276,43 @@ (neg? n) (- n) :else n)) +(defn contract-confirmation-logs [contract-address] + "retrives all log events for the confirmation topic since contract creation" + (some-> contract-address + issues/get-issue-by-contract-address + :transaction_hash + eth/get-transaction-by-hash + :blockNumber + (eth/get-logs contract-address [(:confirmation multisig/topics)]))) + +(defn hash-in-logs? + "return true if the transaction hash is present in the queryable blockchain" + [hash logs] + (some #(= hash (:transactionHash %)) logs)) + +(defn execution-status [execute-hash contract-address] + "check to see if a given execute-hash has been confirmed" + (log/infof "checking contract for logs containing %s" execute-hash) + (let [logs (contract-confirmation-logs contract-address)] + (hash-in-logs? execute-hash logs))) + + +(defn poll-transaction-logs [execute-hash contract-address] + "check for execution hash in logs for a few minutes" + (let [found? (promise) + intervals (take 6 + (periodic-seq (t/now) + (t/seconds 30)))] + ;; polling will be slow but if we want to move to an event driven + ;; model then we can listen for events, rather than logs, once we're + ;; using a geth node again + (chime-at intervals + (fn [time] + (when (execution-status execute-hash contract-address) + (deliver found? true))) + {:on-finished (fn [] + (deliver found? false))}) + @found?)) (defn update-bounty-token-balances "Helper function for updating internal ERC20 token balances to token @@ -400,6 +461,7 @@ (run-tasks [deploy-pending-contracts update-issue-contract-address + update-confirm-hashes update-payout-receipts update-revoked-payout-receipts update-watch-hash @@ -441,40 +503,3 @@ (log/info "stopping scheduler") (scheduler))) -(defn contract-confirmation-logs [contract-address] - "retrives all log events for the confirmation topic since contract creation" - (some-> contract-address - issues/get-issue-by-contract-address - :transaction_hash - eth/get-transaction-by-hash - :blockNumber - (eth/get-logs contract-address [(:confirmation multisig/topics)]))) - -(defn hash-in-logs? - "return true if the transaction hash is present in the queryable blockchain" - [hash logs] - (some #(= hash (:transactionHash %)) logs)) - -(defn execution-status [execute-hash contract-address] - "check to see if a given execute-hash has been confirmed" - (log/infof "checking contract for logs containing %s" execute-hash) - (let [logs (contract-confirmation-logs contract-address)] - (hash-in-logs? execute-hash logs))) - - -(defn poll-transaction-logs [execute-hash contract-address] - "check for execution hash in logs for a few minutes" - (let [found? (promise) - intervals (take 6 - (periodic-seq (t/now) - (t/seconds 30)))] - ;; polling will be slow but if we want to move to an event driven - ;; model then we can listen for events, rather than logs, once we're - ;; using a geth node again - (chime-at intervals - (fn [time] - (when (execution-status execute-hash contract-address) - (deliver found? true))) - {:on-finished (fn [] - (deliver found? false))}) - @found?)) From 56e54e10a4e5954296424e401aa6793c324e8d59 Mon Sep 17 00:00:00 2001 From: Rob Culliton Date: Tue, 1 May 2018 21:59:00 -0400 Subject: [PATCH 03/68] fix logging, error message, inline comments --- src/clj/commiteth/routes/services.clj | 2 +- src/clj/commiteth/scheduler.clj | 3 +-- src/cljs/commiteth/handlers.cljs | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/clj/commiteth/routes/services.clj b/src/clj/commiteth/routes/services.clj index 9f37dcc..797d4e9 100644 --- a/src/clj/commiteth/routes/services.clj +++ b/src/clj/commiteth/routes/services.clj @@ -270,4 +270,4 @@ (ok {:confirm-hash confirm-hash}) (bad-request "The confirm hash could not be updated")) (bad-request "The transaction hash could not be confirmed in a reasonable amount of time")) - (bad-request (str "We were unable to withdraw everything from " contract-address)))))))) + (bad-request (str "Unable to withdraw everything from " contract-address)))))))) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 27706a9..78838a3 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -171,7 +171,7 @@ execute-hash :execute_hash} (db-bounties/pending-payouts)] (update-confirm-hash issue-id execute-hash))) - (log/info "Exit update-confirm-hash")) + (log/info "Exit update-confirm-hashes")) (defn update-watch-hash "Sets watch-hash to NULL for bounties where watch tx has been mined. Used to avoid unneeded watch transactions in update-bounty-token-balances" @@ -502,4 +502,3 @@ :stop (do (log/info "stopping scheduler") (scheduler))) - diff --git a/src/cljs/commiteth/handlers.cljs b/src/cljs/commiteth/handlers.cljs index 4f43b0d..fdc5a5b 100644 --- a/src/cljs/commiteth/handlers.cljs +++ b/src/cljs/commiteth/handlers.cljs @@ -438,7 +438,6 @@ (let [issue-id (:issue_id fields)] {:http {:method POST :url "/api/user/revoke" - ;; merge returned confirm hash with :on-success #(dispatch [:revoke-bounty-success (merge fields %)]) :on-error #(dispatch [:revoke-bounty-error issue-id %]) :params fields}}))) From e10c8b577c2258dc4a2d33411ce50fcf5491545b Mon Sep 17 00:00:00 2001 From: Rob Culliton Date: Tue, 1 May 2018 22:12:28 -0400 Subject: [PATCH 04/68] swap ordering of revoked-payout-receipts and payout-receipts --- src/clj/commiteth/scheduler.clj | 40 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 78838a3..fd8a069 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -227,26 +227,6 @@ (catch Throwable ex (log/error ex "issue %s: update-payout-receipt exception" issue-id)))) -(defn update-revoked-payout-receipts - "Gets transaction receipt for each confirmed revocation and updates payout_hash" - [] - (log/info "In update-revoked-payout-receipts") - (p :update-payout-receipts - (doseq [{issue-id :issue_id - payout-hash :payout_hash - contract-address :contract_address - repo :repo - owner :owner - comment-id :comment_id - issue-number :issue_number - balance-eth :balance_eth - tokens :tokens - confirm-hash :confirm_hash - payee-login :payee_login - updated :updated} (db-bounties/confirmed-revocation-payouts)] - (update-payout-receipt owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated))) - (log/info "Exit update-revoked-payout-receipts")) - (defn update-payout-receipts "Gets transaction receipt for each confirmed payout and updates payout_hash" [] @@ -267,6 +247,26 @@ (update-payout-receipt owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated))) (log/info "Exit update-payout-receipts")) +(defn update-revoked-payout-receipts + "Gets transaction receipt for each confirmed revocation and updates payout_hash" + [] + (log/info "In update-revoked-payout-receipts") + (p :update-payout-receipts + (doseq [{issue-id :issue_id + payout-hash :payout_hash + contract-address :contract_address + repo :repo + owner :owner + comment-id :comment_id + issue-number :issue_number + balance-eth :balance_eth + tokens :tokens + confirm-hash :confirm_hash + payee-login :payee_login + updated :updated} (db-bounties/confirmed-revocation-payouts)] + (update-payout-receipt owner repo comment-id balance-eth tokens payee-login issue-id confirm-hash payout-hash contract-address updated))) + (log/info "Exit update-revoked-payout-receipts")) + (defn abs "(abs n) is the absolute value of n" [n] From 63fd5c336cb3deb5934c167c176200bbcf98678c Mon Sep 17 00:00:00 2001 From: Rob Culliton Date: Wed, 2 May 2018 18:23:39 -0400 Subject: [PATCH 05/68] basic material look for 3 dot button --- resources/templates/home.html | 3 +++ src/cljs/commiteth/manage_payouts.cljs | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/resources/templates/home.html b/resources/templates/home.html index 6afe0ca..1bbc98a 100644 --- a/resources/templates/home.html +++ b/resources/templates/home.html @@ -66,6 +66,9 @@ height="0" width="0" style="display:none;visibility:hidden"> /> + + +