From 62b4394c143315bffc3989c89e09ee84f3619b59 Mon Sep 17 00:00:00 2001 From: Teemu Patja Date: Mon, 18 Dec 2017 12:53:50 +0200 Subject: [PATCH 1/3] Automatic gas price Use ethgasstation API for gas price if :auto-gas-price? is true in config. Fixes: #189 --- src/clj/commiteth/eth/core.clj | 25 ++++++++++++++++++-- src/clj/commiteth/util/crypto_fiat_value.clj | 10 ++------ src/clj/commiteth/util/util.clj | 10 +++++++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/clj/commiteth/eth/core.clj b/src/clj/commiteth/eth/core.clj index b04a0e3..c4c8fa5 100644 --- a/src/clj/commiteth/eth/core.clj +++ b/src/clj/commiteth/eth/core.clj @@ -6,19 +6,40 @@ [clojure.string :refer [join]] [clojure.tools.logging :as log] [clojure.string :as str] - [pandect.core :as pandect])) + [pandect.core :as pandect] + [commiteth.util.util :refer [json-api-request]])) (defn eth-rpc-url [] (env :eth-rpc-url "http://localhost:8545")) (defn eth-account [] (:eth-account env)) (defn eth-password [] (:eth-password env)) (defn gas-estimate-factor [] (env :gas-estimate-factor 1.0)) +(defn auto-gas-price? [] (env :auto-gas-price? false)) -(defn gas-price +(defn eth-gasstation-gas-price [] + (let [data (json-api-request "https://ethgasstation.info/json/ethgasAPI.json") + avg-price (-> (get data "average") + bigint) + avg-price-gwei (/ avg-price (bigint 10))] + (->> (* (bigint (Math/pow 10 9)) avg-price-gwei) ;; for some reason the API returns 10x gwei price + .toBigInteger))) + + +(defn gas-price-from-config [] (-> (:gas-price env 20000000000) ;; 20 gwei default str BigInteger.)) +(defn gas-price + [] + (if (auto-gas-price?) + (try + (eth-gasstation-gas-price) + (catch Throwable t + (log/error "Failed to get gas price with ethgasstation API" t) + (gas-price-from-config))) + (gas-price-from-config))) + (defn eth-rpc [method params] (let [request-id (rand-int 4096) diff --git a/src/clj/commiteth/util/crypto_fiat_value.clj b/src/clj/commiteth/util/crypto_fiat_value.clj index de95b09..07bea89 100644 --- a/src/clj/commiteth/util/crypto_fiat_value.clj +++ b/src/clj/commiteth/util/crypto_fiat_value.clj @@ -1,19 +1,13 @@ (ns commiteth.util.crypto-fiat-value - (:require [clj-http.client :as http] - [mount.core :as mount] + (:require [mount.core :as mount] [clojure.tools.logging :as log] [commiteth.config :refer [env]] - [clojure.data.json :as json])) + [commiteth.util.util :refer [json-api-request]])) (defn fiat-api-provider [] (env :fiat-api-provider :coinmarketcap)) -(defn json-api-request [url] - (->> (http/get url) - (:body) - (json/read-str))) - (defn get-token-usd-price-cryptonator "Get current USD value for a token using cryptonator API" diff --git a/src/clj/commiteth/util/util.clj b/src/clj/commiteth/util/util.clj index 65634c3..f85211e 100644 --- a/src/clj/commiteth/util/util.clj +++ b/src/clj/commiteth/util/util.clj @@ -1,4 +1,7 @@ -(ns commiteth.util.util) +(ns commiteth.util.util + (:require + [clj-http.client :as http] + [clojure.data.json :as json])) (defn eth-decimal->str [n] @@ -6,3 +9,8 @@ (defn usd-decimal->str [n] (format "%.2f" n)) + +(defn json-api-request [url] + (->> (http/get url) + (:body) + (json/read-str))) From a9e178a2f16950ace1b146dd18b1bed128947f04 Mon Sep 17 00:00:00 2001 From: Teemu Patja Date: Mon, 18 Dec 2017 19:31:53 +0200 Subject: [PATCH 2/3] Avoid unneeded watch transactions Store tx id for watch smart contract call while it is pending to avoid sending unneeded transactions. --- .../20171218190701-watch-tx-id.down.sql | 0 .../20171218190701-watch-tx-id.up.sql | 2 ++ resources/sql/queries.sql | 18 ++++++++++++- src/clj/commiteth/db/bounties.clj | 10 ++++++++ src/clj/commiteth/scheduler.clj | 25 +++++++++++++++---- 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 resources/migrations/20171218190701-watch-tx-id.down.sql create mode 100644 resources/migrations/20171218190701-watch-tx-id.up.sql diff --git a/resources/migrations/20171218190701-watch-tx-id.down.sql b/resources/migrations/20171218190701-watch-tx-id.down.sql new file mode 100644 index 0000000..e69de29 diff --git a/resources/migrations/20171218190701-watch-tx-id.up.sql b/resources/migrations/20171218190701-watch-tx-id.up.sql new file mode 100644 index 0000000..84b7f32 --- /dev/null +++ b/resources/migrations/20171218190701-watch-tx-id.up.sql @@ -0,0 +1,2 @@ +ALTER TABLE "public"."issues" + ADD COLUMN "watch_hash" character varying(128); diff --git a/resources/sql/queries.sql b/resources/sql/queries.sql index 228e416..074fd57 100644 --- a/resources/sql/queries.sql +++ b/resources/sql/queries.sql @@ -339,6 +339,21 @@ UPDATE issues SET winner_login = :winner_login WHERE issue_id = :issue_id; +-- :name update-watch-hash :! :n +-- :doc updates issue with watch transaction hash +UPDATE issues +SET watch_hash = :watch_hash +WHERE issue_id = :issue_id; + +-- :name pending-watch-calls :? :* +-- :doc issues with a pending watch transaction +SELECT +issue_id, +watch_hash +FROM issues +WHERE watch_hash IS NOT NULL; + + -- :name update-payout-hash :! :n -- :doc updates issue with payout transaction hash UPDATE issues @@ -492,7 +507,8 @@ SELECT i.issue_id AS issue_id, i.balance_eth AS balance_eth, i.tokens AS tokens, - i.value_usd AS value_usd + i.value_usd AS value_usd, + i.watch_hash AS watch_hash FROM issues i, repositories r WHERE r.repo_id = i.repo_id AND contract_address IS NOT NULL diff --git a/src/clj/commiteth/db/bounties.clj b/src/clj/commiteth/db/bounties.clj index 0032df2..ff1d14e 100644 --- a/src/clj/commiteth/db/bounties.clj +++ b/src/clj/commiteth/db/bounties.clj @@ -55,6 +55,16 @@ (jdbc/with-db-connection [con-db *db*] (db/update-winner-login con-db {:issue_id issue-id :winner_login login}))) +(defn update-watch-hash + [issue-id watch-hash] + (jdbc/with-db-connection [con-db *db*] + (db/update-watch-hash con-db {:issue_id issue-id :watch_hash watch-hash}))) + +(defn pending-watch-calls + [] + (jdbc/with-db-connection [con-db *db*] + (db/pending-watch-calls con-db))) + (defn update-payout-hash [issue-id payout-hash] (jdbc/with-db-connection [con-db *db*] diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index 4f1e26b..cef1792 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -129,6 +129,16 @@ (db-bounties/update-confirm-hash issue-id 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" + [] + (doseq [{issue-id :issue_id + watch-hash :watch_hash} (db-bounties/pending-watch-calls)] + (log/info "pending watch call" watch-hash) + (when-let [receipt (eth/get-transaction-receipt watch-hash)] + (db-bounties/update-watch-hash issue-id nil)))) + + (defn older-than-3h? [timestamp] (let [now (t/now) @@ -198,23 +208,27 @@ (defn update-bounty-token-balances "Helper function for updating internal ERC20 token balances to token multisig contract. Will be called periodically for all open bounty contracts." - [bounty-addr] + [issue-id bounty-addr watch-hash] (doseq [[tla token-data] (token-data/as-map)] (let [balance (multisig/token-balance bounty-addr tla)] (when (> balance 0) (do (log/debug "bounty at" bounty-addr "has" balance "of token" tla) (let [internal-balance (multisig/token-balance-in-bounty bounty-addr tla)] - (when (not= balance internal-balance) + (when (and (nil? watch-hash) + (not= balance internal-balance)) (log/info "balances not in sync, calling watch") - (multisig/watch-token bounty-addr tla)))))))) + (let [hash (multisig/watch-token bounty-addr tla)] + (db-bounties/update-watch-hash issue-id hash))))))))) (defn update-contract-internal-balances "It is required in our current smart contract to manually update it's internal balance when some tokens have been added." [] - (doseq [{bounty-address :contract_address} + (doseq [{issue-id :issue_id + bounty-address :contract_address + watch-hash :watch_hash} (db-bounties/open-bounty-contracts)] - (update-bounty-token-balances bounty-address))) + (update-bounty-token-balances issue-id bounty-address watch-hash))) (defn get-bounty-funds @@ -313,6 +327,7 @@ update-issue-contract-address update-confirm-hash update-payout-receipt + update-watch-hash self-sign-bounty update-contract-internal-balances update-balances]) From 40ba44bb140be589cb4a9adb454389656d78cdac Mon Sep 17 00:00:00 2001 From: Teemu Patja Date: Wed, 20 Dec 2017 14:49:59 +0200 Subject: [PATCH 3/3] Improve logging --- src/clj/commiteth/scheduler.clj | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/clj/commiteth/scheduler.clj b/src/clj/commiteth/scheduler.clj index cef1792..fd84030 100644 --- a/src/clj/commiteth/scheduler.clj +++ b/src/clj/commiteth/scheduler.clj @@ -23,8 +23,9 @@ transaction-hash :transaction_hash} (issues/list-pending-deployments)] (log/debug "pending deployment:" transaction-hash) (when-let [receipt (eth/get-transaction-receipt transaction-hash)] - (log/info "transaction receipt for issue #" issue-id ": " receipt) - (when-let [contract-address (multisig/find-created-multisig-address receipt)] + (log/info "update-issue-contract-address: transaction receipt for issue #" + issue-id ": " receipt) + (if-let [contract-address (multisig/find-created-multisig-address receipt)] (let [issue (issues/update-contract-address issue-id contract-address) {owner :owner repo :repo @@ -32,6 +33,7 @@ issue-number :issue_number} issue balance-eth-str (eth/get-balance-eth contract-address 6) balance-eth (read-string balance-eth-str)] + (log/info "Updating comment image") (bounties/update-bounty-comment-image issue-id owner repo @@ -40,6 +42,7 @@ balance-eth balance-eth-str {}) + (log/info "Updating comment") (github/update-comment owner repo comment-id @@ -47,7 +50,8 @@ contract-address balance-eth balance-eth-str - {})))))) + {})) + (log/error "Failed to find contract address in tx logs"))))) (defn deploy-contract [owner-address issue-id]