mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-11 07:20:19 +00:00
update deps
This commit is contained in:
@@ -1,24 +1,6 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
|
||||
|
||||
## [Unreleased]
|
||||
## 0.2.0 - 2020-11-09
|
||||
### Changed
|
||||
- Add a new arity to `make-widget-async` to provide a different widget shape.
|
||||
|
||||
## [0.1.1] - 2017-06-05
|
||||
### Changed
|
||||
- Documentation on how to make the widgets.
|
||||
|
||||
### Removed
|
||||
- `make-widget-sync` - we're all async, all the time.
|
||||
|
||||
### Fixed
|
||||
- Fixed widget maker to keep working when daylight savings switches over.
|
||||
|
||||
## 0.1.0 - 2017-06-05
|
||||
### Added
|
||||
- Files from the new template.
|
||||
- Widget maker public API - `make-widget-sync`.
|
||||
|
||||
[Unreleased]: https://github.com/your-name/jepsen.tendermint/compare/0.1.1...HEAD
|
||||
[0.1.1]: https://github.com/your-name/jepsen.tendermint/compare/0.1.0...0.1.1
|
||||
- Upgraded deps (jepsen 0.2.1)
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
(defproject jepsen.tendermint "0.1.0"
|
||||
(defproject jepsen.tendermint "0.2.0"
|
||||
:description "Jepsen tests for the Tendermint Byzantine consensus system"
|
||||
:url "http://github.com/jepsen-io/tendermint"
|
||||
:license {:name "Apache License, version 2.0"
|
||||
:url "https://www.apache.org/licenses/LICENSE-2.0"}
|
||||
:dependencies [[org.clojure/clojure "1.8.0"]
|
||||
[org.clojure/core.typed "0.4.0"]
|
||||
[cheshire "5.7.1"]
|
||||
:dependencies [[org.clojure/clojure "1.10.1"]
|
||||
[typed.clj/runtime "1.0.12"]
|
||||
[cheshire "5.10.0"]
|
||||
[slingshot "0.12.2"]
|
||||
[clj-http "3.6.1"]
|
||||
[jepsen "0.1.6"]]
|
||||
[clj-http "3.10.3"]
|
||||
[jepsen "0.2.1"]]
|
||||
:profiles {:dev {:dependencies [[typed.clj/checker "1.0.12"]]}}
|
||||
:jvm-opts ["-Xmx6g"
|
||||
"-XX:+UseConcMarkSweepGC"
|
||||
"-XX:+UseParNewGC"
|
||||
@@ -19,6 +20,7 @@
|
||||
"-XX:MaxRecursiveInlineLevel=2"
|
||||
"-XX:-OmitStackTraceInFastThrow"
|
||||
"-server"]
|
||||
:plugins [[lein-cljfmt "0.7.0"]]
|
||||
:main jepsen.tendermint.cli
|
||||
:injections [(require 'clojure.core.typed)
|
||||
(clojure.core.typed/install)])
|
||||
|
||||
@@ -11,18 +11,17 @@
|
||||
:default :cas-register
|
||||
:parse-fn keyword]
|
||||
[nil "--nemesis NEMESIS" "Nemesis to use; e.g. clocks"
|
||||
:default :none
|
||||
:parse-fn keyword]
|
||||
:default :none
|
||||
:parse-fn keyword]
|
||||
[nil "--dup-validators" "Whether to have multiple validators share the same key."]
|
||||
[nil "--super-byzantine-validators" "Should byzantine validators have just shy of 2/3 the voting weight?"]
|
||||
(jc/package-opt "tendermint-url" "https://github.com/tendermint/tendermint/releases/download/v0.33.8/tendermint_v0.33.8_linux_amd64.zip")
|
||||
(jc/package-opt "merkleeyes-url" "")
|
||||
(jc/package-opt "abci-url" "")])
|
||||
|
||||
|
||||
(defn -main
|
||||
[& args]
|
||||
(jc/run! (merge (jc/serve-cmd)
|
||||
(jc/single-test-cmd {:test-fn core/test
|
||||
:opt-spec opts}))
|
||||
args))
|
||||
args))
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
(loop [i 0]
|
||||
(when (< i n)
|
||||
(aset a i (unchecked-byte (Integer/parseInt
|
||||
(subs s (* i 2) (+ (* i 2) 2)) 16)))
|
||||
(subs s (* i 2) (+ (* i 2) 2)) 16)))
|
||||
(recur (inc i))))
|
||||
(ByteBuffer/wrap a)))
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
0 tx
|
||||
4 (throw+ {:type :unauthorized :log (:log tx)})
|
||||
111 (throw+ {:type :base-unknown-address, :log (:log tx)})
|
||||
(throw+ (assoc tx :type :unknown-tx-error))))
|
||||
(throw+ (assoc tx :type :unknown-tx-error))))
|
||||
|
||||
(def port "HTTP interface port" 26657)
|
||||
|
||||
@@ -146,11 +146,11 @@
|
||||
"Reads the current validator set, transactionally."
|
||||
[node]
|
||||
(-> (broadcast-tx! node (tx :validator-set-read))
|
||||
:deliver_tx
|
||||
:data
|
||||
hex->byte-buf
|
||||
(bs/convert java.io.Reader)
|
||||
(json/parse-stream true)))
|
||||
:deliver_tx
|
||||
:data
|
||||
hex->byte-buf
|
||||
(bs/convert java.io.Reader)
|
||||
(json/parse-stream true)))
|
||||
|
||||
(defn validator-set-change!
|
||||
"Change the weight of a validator, given by private key (a hex string), and a
|
||||
|
||||
@@ -22,10 +22,9 @@
|
||||
[jepsen.os.debian :as debian]
|
||||
[cheshire.core :as json]
|
||||
[jepsen.tendermint [client :as tc]
|
||||
[db :as td]
|
||||
[util :refer [base-dir]]
|
||||
[validator :as tv]]
|
||||
))
|
||||
[db :as td]
|
||||
[util :refer [base-dir]]
|
||||
[validator :as tv]]))
|
||||
|
||||
(defn r [_ _] {:type :invoke, :f :read, :value nil})
|
||||
(defn w [_ _] {:type :invoke, :f :write, :value (rand-int 10)})
|
||||
@@ -45,39 +44,38 @@
|
||||
:fail
|
||||
:info)]
|
||||
(try+
|
||||
(case (:f op)
|
||||
:read (assoc op
|
||||
:type :ok
|
||||
:value (independent/tuple k (tc/read node k)))
|
||||
:write (do (tc/write! node k v)
|
||||
(assoc op :type :ok))
|
||||
:cas (let [[v v'] v]
|
||||
(tc/cas! node k v v')
|
||||
(assoc op :type :ok)))
|
||||
(case (:f op)
|
||||
:read (assoc op
|
||||
:type :ok
|
||||
:value (independent/tuple k (tc/read node k)))
|
||||
:write (do (tc/write! node k v)
|
||||
(assoc op :type :ok))
|
||||
:cas (let [[v v'] v]
|
||||
(tc/cas! node k v v')
|
||||
(assoc op :type :ok)))
|
||||
|
||||
(catch [:type :unauthorized] e
|
||||
(assoc op :type :fail, :error :precondition-failed))
|
||||
(catch [:type :unauthorized] e
|
||||
(assoc op :type :fail, :error :precondition-failed))
|
||||
|
||||
(catch [:type :base-unknown-address] e
|
||||
(assoc op :type :fail, :error :not-found))
|
||||
(catch [:type :base-unknown-address] e
|
||||
(assoc op :type :fail, :error :not-found))
|
||||
|
||||
(catch org.apache.http.NoHttpResponseException e
|
||||
(assoc op :type crash, :error :no-http-response))
|
||||
(catch org.apache.http.NoHttpResponseException e
|
||||
(assoc op :type crash, :error :no-http-response))
|
||||
|
||||
(catch java.net.ConnectException e
|
||||
(condp re-find (.getMessage e)
|
||||
#"Connection refused"
|
||||
(assoc op :type :fail, :error :connection-refused)
|
||||
(catch java.net.ConnectException e
|
||||
(condp re-find (.getMessage e)
|
||||
#"Connection refused"
|
||||
(assoc op :type :fail, :error :connection-refused)
|
||||
|
||||
(assoc op :type crash, :error [:connect-exception
|
||||
(.getMessage e)])))
|
||||
(assoc op :type crash, :error [:connect-exception
|
||||
(.getMessage e)])))
|
||||
|
||||
(catch java.net.SocketTimeoutException e
|
||||
(assoc op :type crash, :error :timeout)))))
|
||||
(catch java.net.SocketTimeoutException e
|
||||
(assoc op :type crash, :error :timeout)))))
|
||||
|
||||
(teardown! [_ test]))))
|
||||
|
||||
|
||||
(defn set-client
|
||||
([]
|
||||
(set-client nil))
|
||||
@@ -92,45 +90,45 @@
|
||||
:fail
|
||||
:info)]
|
||||
(try+
|
||||
(case (:f op)
|
||||
:init (with-retry [tries 0]
|
||||
(tc/write! node k [])
|
||||
(assoc op :type :ok)
|
||||
(catch Exception e
|
||||
(if (<= 10 tries)
|
||||
(throw e)
|
||||
(do (info "Couldn't initialize key" k ":" (.getMessage e) "- retrying")
|
||||
(Thread/sleep (* 50 (Math/pow 2 tries)))
|
||||
(retry (inc tries))))))
|
||||
:add (let [s (or (vec (tc/read node k)) [])
|
||||
s' (conj s v)]
|
||||
(tc/cas! node k s s')
|
||||
(assoc op :type :ok))
|
||||
:read (assoc op
|
||||
:type :ok
|
||||
:value (independent/tuple
|
||||
k
|
||||
(into (sorted-set) (tc/read node k)))))
|
||||
(case (:f op)
|
||||
:init (with-retry [tries 0]
|
||||
(tc/write! node k [])
|
||||
(assoc op :type :ok)
|
||||
(catch Exception e
|
||||
(if (<= 10 tries)
|
||||
(throw e)
|
||||
(do (info "Couldn't initialize key" k ":" (.getMessage e) "- retrying")
|
||||
(Thread/sleep (* 50 (Math/pow 2 tries)))
|
||||
(retry (inc tries))))))
|
||||
:add (let [s (or (vec (tc/read node k)) [])
|
||||
s' (conj s v)]
|
||||
(tc/cas! node k s s')
|
||||
(assoc op :type :ok))
|
||||
:read (assoc op
|
||||
:type :ok
|
||||
:value (independent/tuple
|
||||
k
|
||||
(into (sorted-set) (tc/read node k)))))
|
||||
|
||||
(catch [:type :unauthorized] e
|
||||
(assoc op :type :fail, :error :precondition-failed))
|
||||
(catch [:type :unauthorized] e
|
||||
(assoc op :type :fail, :error :precondition-failed))
|
||||
|
||||
(catch [:type :base-unknown-address] e
|
||||
(assoc op :type :fail, :error :not-found))
|
||||
(catch [:type :base-unknown-address] e
|
||||
(assoc op :type :fail, :error :not-found))
|
||||
|
||||
(catch org.apache.http.NoHttpResponseException e
|
||||
(assoc op :type crash, :error :no-http-response))
|
||||
(catch org.apache.http.NoHttpResponseException e
|
||||
(assoc op :type crash, :error :no-http-response))
|
||||
|
||||
(catch java.net.ConnectException e
|
||||
(condp re-find (.getMessage e)
|
||||
#"Connection refused"
|
||||
(assoc op :type :fail, :error :connection-refused)
|
||||
(catch java.net.ConnectException e
|
||||
(condp re-find (.getMessage e)
|
||||
#"Connection refused"
|
||||
(assoc op :type :fail, :error :connection-refused)
|
||||
|
||||
(assoc op :type crash, :error [:connect-exception
|
||||
(.getMessage e)])))
|
||||
(assoc op :type crash, :error [:connect-exception
|
||||
(.getMessage e)])))
|
||||
|
||||
(catch java.net.SocketTimeoutException e
|
||||
(assoc op :type crash, :error :timeout)))))
|
||||
(catch java.net.SocketTimeoutException e
|
||||
(assoc op :type crash, :error :timeout)))))
|
||||
|
||||
(teardown! [_ test]))))
|
||||
|
||||
@@ -144,15 +142,15 @@
|
||||
; main component, and compute the remaining complement for each dup
|
||||
; group.
|
||||
(let [{:keys [groups singles dups]} (tv/dup-groups
|
||||
@(:validator-config test))
|
||||
@(:validator-config test))
|
||||
chosen-ones (map (comp hash-set rand-nth vec) dups)
|
||||
exiles (map remove chosen-ones dups)]
|
||||
(nemesis/complete-grudge
|
||||
(cons ; Main group
|
||||
(set (concat (apply concat singles)
|
||||
(apply concat chosen-ones)))
|
||||
(cons ; Main group
|
||||
(set (concat (apply concat singles)
|
||||
(apply concat chosen-ones)))
|
||||
; Exiles
|
||||
exiles)))))
|
||||
exiles)))))
|
||||
|
||||
(defn split-dup-validators-grudge
|
||||
"Takes a test. Returns a function which takes a collection of nodes from that
|
||||
@@ -162,18 +160,18 @@
|
||||
[test]
|
||||
(fn [nodes]
|
||||
(let [{:keys [groups singles dups]} (tv/dup-groups
|
||||
@(:validator-config test))
|
||||
@(:validator-config test))
|
||||
n (reduce max (map count dups))]
|
||||
(->> groups
|
||||
shuffle
|
||||
(map shuffle)
|
||||
(apply concat)
|
||||
(reduce (fn [[components i] node]
|
||||
[(update components (mod i n) conj node)
|
||||
(inc i)])
|
||||
[[] 0])
|
||||
first
|
||||
nemesis/complete-grudge))))
|
||||
(->> groups
|
||||
shuffle
|
||||
(map shuffle)
|
||||
(apply concat)
|
||||
(reduce (fn [[components i] node]
|
||||
[(update components (mod i n) conj node)
|
||||
(inc i)])
|
||||
[[] 0])
|
||||
first
|
||||
nemesis/complete-grudge))))
|
||||
|
||||
(defn crash-truncate-nemesis
|
||||
"A nemesis which kills tendermint, kills merkleeyes, truncates the merkleeyes
|
||||
@@ -195,9 +193,9 @@
|
||||
(td/stop-tendermint! test node)
|
||||
(td/stop-merkleeyes! test node)
|
||||
(c/su
|
||||
(c/exec :truncate :-c :-s
|
||||
(str "-" (rand-int 1048576))
|
||||
(str base-dir file)))
|
||||
(c/exec :truncate :-c :-s
|
||||
(str "-" (rand-int 1048576))
|
||||
(str base-dir file)))
|
||||
(td/start-merkleeyes! test node)
|
||||
(td/start-tendermint! test node))))
|
||||
op)
|
||||
@@ -266,7 +264,7 @@
|
||||
; state to reflect the new state of things.
|
||||
(swap! (:validator-config test) #(tv/post-step % t)))))
|
||||
|
||||
(assoc op :value :done))
|
||||
(assoc op :value :done))
|
||||
|
||||
(teardown! [this test])))
|
||||
|
||||
@@ -278,11 +276,11 @@
|
||||
:generator (gen/stagger 10 (tv/generator))}
|
||||
|
||||
:peekaboo-dup-validators {:nemesis (nemesis/partitioner
|
||||
(peekaboo-dup-validators-grudge test))
|
||||
(peekaboo-dup-validators-grudge test))
|
||||
:generator (gen/start-stop 0 5)}
|
||||
|
||||
:split-dup-validators {:nemesis (nemesis/partitioner
|
||||
(split-dup-validators-grudge test))
|
||||
(split-dup-validators-grudge test))
|
||||
:generator (gen/once {:type :info, :f :start})}
|
||||
|
||||
:half-partitions {:nemesis (nemesis/partition-random-halves)
|
||||
@@ -301,12 +299,12 @@
|
||||
:generator (gen/start-stop 15 0)}
|
||||
|
||||
:truncate-merkleeyes {:nemesis (crash-truncate-nemesis
|
||||
test 1/3 "/jepsen/jepsen.db/000001.log")
|
||||
test 1/3 "/jepsen/jepsen.db/000001.log")
|
||||
:generator (->> {:type :info, :f :crash}
|
||||
(gen/delay 10))}
|
||||
|
||||
:truncate-tendermint {:nemesis (crash-truncate-nemesis
|
||||
test 1/3 "/data/cs.wal/wal")
|
||||
test 1/3 "/data/cs.wal/wal")
|
||||
:generator (->> {:type :info, :f :crash}
|
||||
(gen/delay 10))}
|
||||
|
||||
@@ -336,76 +334,75 @@
|
||||
:cas-register {:client (cas-register-client)
|
||||
:model (model/cas-register)
|
||||
:generator (independent/concurrent-generator
|
||||
(* 2 n)
|
||||
(range)
|
||||
(fn [k]
|
||||
(->> (gen/mix [w cas])
|
||||
(gen/reserve n r)
|
||||
(gen/stagger 1)
|
||||
(gen/limit 120))))
|
||||
(* 2 n)
|
||||
(range)
|
||||
(fn [k]
|
||||
(->> (gen/mix [w cas])
|
||||
(gen/reserve n r)
|
||||
(gen/stagger 1)
|
||||
(gen/limit 120))))
|
||||
:final-generator nil
|
||||
:checker {:linear (independent/checker
|
||||
(checker/linearizable))}}
|
||||
(checker/linearizable))}}
|
||||
:set
|
||||
(let [keys (atom [])]
|
||||
{:client (set-client)
|
||||
:model nil
|
||||
:generator (independent/concurrent-generator
|
||||
n
|
||||
(range)
|
||||
(fn [k]
|
||||
(swap! keys conj k)
|
||||
(gen/phases
|
||||
(gen/once {:type :invoke, :f :init})
|
||||
(->> (range)
|
||||
(map (fn [x]
|
||||
{:type :invoke
|
||||
:f :add
|
||||
:value x}))
|
||||
gen/seq
|
||||
(gen/stagger 1/2)))))
|
||||
n
|
||||
(range)
|
||||
(fn [k]
|
||||
(swap! keys conj k)
|
||||
(gen/phases
|
||||
(gen/once {:type :invoke, :f :init})
|
||||
(->> (range)
|
||||
(map (fn [x]
|
||||
{:type :invoke
|
||||
:f :add
|
||||
:value x}))
|
||||
gen/seq
|
||||
(gen/stagger 1/2)))))
|
||||
:final-generator (deref-gen
|
||||
(delay
|
||||
(locking keys
|
||||
(independent/concurrent-generator
|
||||
n
|
||||
@keys
|
||||
(fn [k]
|
||||
(gen/each (gen/once {:type :invoke
|
||||
:f :read})))))))
|
||||
(delay
|
||||
(locking keys
|
||||
(independent/concurrent-generator
|
||||
n
|
||||
@keys
|
||||
(fn [k]
|
||||
(gen/each (gen/once {:type :invoke
|
||||
:f :read})))))))
|
||||
:checker {:set (independent/checker (checker/set))}}))))
|
||||
|
||||
|
||||
(defn test
|
||||
[opts]
|
||||
(let [validator-config (atom nil)
|
||||
test (merge
|
||||
tests/noop-test
|
||||
opts
|
||||
{:name (str "tendermint " (name (:workload opts)) " "
|
||||
(name (:nemesis opts)))
|
||||
:os debian/os
|
||||
:nonserializable-keys [:validator-config]
|
||||
:validator-config validator-config})
|
||||
tests/noop-test
|
||||
opts
|
||||
{:name (str "tendermint " (name (:workload opts)) " "
|
||||
(name (:nemesis opts)))
|
||||
:os debian/os
|
||||
:nonserializable-keys [:validator-config]
|
||||
:validator-config validator-config})
|
||||
db (td/db test)
|
||||
nemesis (nemesis test)
|
||||
workload (workload test)
|
||||
checker (checker/compose
|
||||
(merge {:timeline (independent/checker (timeline/html))
|
||||
:perf (checker/perf)}
|
||||
(:checker workload)))
|
||||
(merge {:timeline (independent/checker (timeline/html))
|
||||
:perf (checker/perf)}
|
||||
(:checker workload)))
|
||||
test (merge test
|
||||
{:db db
|
||||
:client (:client workload)
|
||||
:generator (gen/phases
|
||||
(->> (:generator workload)
|
||||
(gen/nemesis (:generator nemesis))
|
||||
(gen/time-limit (:time-limit opts)))
|
||||
(gen/nemesis
|
||||
(gen/once {:type :info, :f :stop}))
|
||||
(gen/sleep 30)
|
||||
(gen/clients
|
||||
(:final-generator workload)))
|
||||
(->> (:generator workload)
|
||||
(gen/nemesis (:generator nemesis))
|
||||
(gen/time-limit (:time-limit opts)))
|
||||
(gen/nemesis
|
||||
(gen/once {:type :info, :f :stop}))
|
||||
(gen/sleep 30)
|
||||
(gen/clients
|
||||
(:final-generator workload)))
|
||||
:nemesis (:nemesis nemesis)
|
||||
:model (:model workload)
|
||||
:checker checker})]
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[slingshot.slingshot :refer [try+]]
|
||||
[jepsen [core :as jepsen]
|
||||
[control :as c]
|
||||
[db :as db]
|
||||
[util :as util :refer [timeout with-retry map-vals]]]
|
||||
[control :as c]
|
||||
[db :as db]
|
||||
[util :as util :refer [timeout with-retry map-vals]]]
|
||||
[jepsen.control.util :as cu]
|
||||
[jepsen.os.debian :as debian]
|
||||
[jepsen.nemesis.time :as nt]
|
||||
[cheshire.core :as json]
|
||||
[jepsen.tendermint [client :as tc]
|
||||
[util :refer [base-dir]]
|
||||
[validator :as tv]]))
|
||||
[util :refer [base-dir]]
|
||||
[validator :as tv]]))
|
||||
|
||||
(defn install-component!
|
||||
"Download and install a tendermint component"
|
||||
@@ -29,27 +29,27 @@
|
||||
"Writes out the given validator structure to priv_validator.json."
|
||||
[validator]
|
||||
(c/su
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (json/generate-string validator)
|
||||
:> "priv_validator_key.json")
|
||||
(info "Wrote priv_validator_key.json"))))
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (json/generate-string validator)
|
||||
:> "priv_validator_key.json")
|
||||
(info "Wrote priv_validator_key.json"))))
|
||||
|
||||
(defn write-genesis!
|
||||
"Writes a genesis structure to a JSON file on disk."
|
||||
[genesis]
|
||||
(c/su
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (json/generate-string genesis)
|
||||
:> "genesis.json")
|
||||
(info "Wrote genesis.json"))))
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (json/generate-string genesis)
|
||||
:> "genesis.json")
|
||||
(info "Wrote genesis.json"))))
|
||||
|
||||
(defn write-config!
|
||||
"Writes out a config.toml file to the current node."
|
||||
[]
|
||||
(c/su
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (slurp (io/resource "config.toml"))
|
||||
:> "config.toml"))))
|
||||
(c/cd base-dir
|
||||
(c/exec :echo (slurp (io/resource "config.toml"))
|
||||
:> "config.toml"))))
|
||||
|
||||
(defn seeds
|
||||
"Constructs a --seeds command line for a test, so a tendermint node knows
|
||||
@@ -74,31 +74,31 @@
|
||||
"Starts tendermint as a daemon."
|
||||
[test node]
|
||||
(c/su
|
||||
(c/cd base-dir
|
||||
(cu/start-daemon!
|
||||
{:logfile tendermint-logfile
|
||||
:pidfile tendermint-pidfile
|
||||
:chdir base-dir}
|
||||
"./tendermint"
|
||||
:--home base-dir
|
||||
:node
|
||||
:--proxy_app socket
|
||||
:--p2p.seeds (seeds test node))))
|
||||
(c/cd base-dir
|
||||
(cu/start-daemon!
|
||||
{:logfile tendermint-logfile
|
||||
:pidfile tendermint-pidfile
|
||||
:chdir base-dir}
|
||||
"./tendermint"
|
||||
:--home base-dir
|
||||
:node
|
||||
:--proxy_app socket
|
||||
:--p2p.seeds (seeds test node))))
|
||||
:started)
|
||||
|
||||
(defn start-merkleeyes!
|
||||
"Starts merkleeyes as a daemon."
|
||||
[test node]
|
||||
(c/su
|
||||
(c/cd base-dir
|
||||
(cu/start-daemon!
|
||||
{:logfile merkleeyes-logfile
|
||||
:pidfile merkleeyes-pidfile
|
||||
:chdir base-dir}
|
||||
"./merkleeyes"
|
||||
:start
|
||||
:--dbName "jepsen"
|
||||
:--address socket)))
|
||||
(c/cd base-dir
|
||||
(cu/start-daemon!
|
||||
{:logfile merkleeyes-logfile
|
||||
:pidfile merkleeyes-pidfile
|
||||
:chdir base-dir}
|
||||
"./merkleeyes"
|
||||
:start
|
||||
:--dbName "jepsen"
|
||||
:--address socket)))
|
||||
:started)
|
||||
|
||||
(defn stop-tendermint! [test node]
|
||||
@@ -146,46 +146,45 @@
|
||||
(reify db/DB
|
||||
(setup! [_ test node]
|
||||
(c/su
|
||||
(install-component! "tendermint" opts)
|
||||
(install-component! "abci" opts)
|
||||
(install-component! "merkleeyes" opts)
|
||||
(install-component! "tendermint" opts)
|
||||
(install-component! "abci" opts)
|
||||
(install-component! "merkleeyes" opts)
|
||||
|
||||
(write-config!)
|
||||
(write-config!)
|
||||
|
||||
; OK we're ready to compute the initial validator config.
|
||||
(jepsen/synchronize test)
|
||||
(when (= node (jepsen/primary test))
|
||||
(let [validator-config (tv/initial-config test)]
|
||||
(info :initial-config (with-out-str (pprint validator-config)))
|
||||
(assert (compare-and-set! (:validator-config opts)
|
||||
nil
|
||||
validator-config)
|
||||
"Initial validator config already established!")))
|
||||
(jepsen/synchronize test)
|
||||
(when (= node (jepsen/primary test))
|
||||
(let [validator-config (tv/initial-config test)]
|
||||
(info :initial-config (with-out-str (pprint validator-config)))
|
||||
(assert (compare-and-set! (:validator-config opts)
|
||||
nil
|
||||
validator-config)
|
||||
"Initial validator config already established!")))
|
||||
|
||||
; Now apply that config.
|
||||
(jepsen/synchronize test)
|
||||
(let [vc @(:validator-config opts)]
|
||||
(write-genesis! (tv/genesis vc))
|
||||
(write-validator! (get (:validators vc)
|
||||
(get-in vc [:nodes node]))))
|
||||
(jepsen/synchronize test)
|
||||
(let [vc @(:validator-config opts)]
|
||||
(write-genesis! (tv/genesis vc))
|
||||
(write-validator! (get (:validators vc)
|
||||
(get-in vc [:nodes node]))))
|
||||
|
||||
(start-merkleeyes! test node)
|
||||
(start-tendermint! test node)
|
||||
(start-merkleeyes! test node)
|
||||
(start-tendermint! test node)
|
||||
|
||||
(nt/install!)
|
||||
(nt/install!)
|
||||
|
||||
(Thread/sleep 1000)))
|
||||
(Thread/sleep 1000)))
|
||||
|
||||
(teardown! [_ test node]
|
||||
(stop-merkleeyes! test node)
|
||||
(stop-tendermint! test node)
|
||||
(c/su
|
||||
(c/exec :rm :-rf base-dir)))
|
||||
(c/exec :rm :-rf base-dir)))
|
||||
|
||||
db/LogFiles
|
||||
(log-files [_ test node]
|
||||
[tendermint-logfile
|
||||
merkleeyes-logfile
|
||||
(str base-dir "/priv_validator.json")
|
||||
(str base-dir "/genesis.json")
|
||||
])))
|
||||
(str base-dir "/genesis.json")])))
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
Writable
|
||||
(byte-size [_] (.remaining x))
|
||||
(write! [_ buf]
|
||||
(.put buf x)
|
||||
buf))
|
||||
(.put buf x)
|
||||
buf))
|
||||
|
||||
(defn fixed-bytes
|
||||
[x]
|
||||
@@ -57,14 +57,14 @@
|
||||
Long
|
||||
(byte-size [n]
|
||||
(cond (< n 0x0) (throw (IllegalArgumentException.
|
||||
(str "Number " n " can't be negative")))
|
||||
(str "Number " n " can't be negative")))
|
||||
(<= n 0x0) 1
|
||||
(<= n 0xff) 2
|
||||
(<= n 0xffff) 3
|
||||
(<= n 0xffffff) 4
|
||||
(<= n 0xffffffff) 5
|
||||
true (throw (IllegalArgumentException.
|
||||
(str "Number " n " is too large")))))
|
||||
(str "Number " n " is too large")))))
|
||||
|
||||
(write! [n buf]
|
||||
(let [int-size (dec (byte-size n))]
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
[cheshire.core :as json]
|
||||
[dom-top.core :as dt]
|
||||
[jepsen.tendermint [client :as tc]
|
||||
[util :refer [base-dir]]]
|
||||
[util :refer [base-dir]]]
|
||||
[jepsen [util :as util :refer [map-vals]]
|
||||
[control :as c]
|
||||
[client :as client]
|
||||
[nemesis :as nemesis]
|
||||
[generator :as gen]])
|
||||
[control :as c]
|
||||
[client :as client]
|
||||
[nemesis :as nemesis]
|
||||
[generator :as gen]])
|
||||
(:import (clojure.tools.logging.impl LoggerFactory Logger)
|
||||
(clojure.lang Namespace
|
||||
Symbol)))
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
; Domain types
|
||||
|
||||
|
||||
(t/defalias Node
|
||||
"Jepsen nodes are strings."
|
||||
String)
|
||||
@@ -152,13 +153,13 @@
|
||||
(t/ann ^:no-check clojure.core/update
|
||||
(t/All [m k v v' arg ...]
|
||||
(t/IFn
|
||||
[m k [v arg ... arg -> v'] arg ... arg -> (t/Assoc m k v')])))
|
||||
[m k [v arg ... arg -> v'] arg ... arg -> (t/Assoc m k v')])))
|
||||
|
||||
(t/ann ^:no-check clojure.tools.logging/*logger-factory* LoggerFactory)
|
||||
|
||||
(t/ann ^:no-check clojure.tools.logging.impl/get-logger
|
||||
[LoggerFactory (t/U clojure.lang.Symbol Namespace)
|
||||
-> clojure.tools.logging.impl.Logger])
|
||||
-> clojure.tools.logging.impl.Logger])
|
||||
|
||||
(t/ann ^:no-check clojure.tools.logging.impl/enabled?
|
||||
[Logger t/Keyword -> Boolean])
|
||||
@@ -177,7 +178,7 @@
|
||||
[Test (t/NonEmptyColl Node) [Test Node -> res]
|
||||
-> (t/I (t/Map Node res)
|
||||
(t/NonEmptySeqable
|
||||
(clojure.lang.AMapEntry Node res)))])))
|
||||
(clojure.lang.AMapEntry Node res)))])))
|
||||
|
||||
(t/ann ^:no-check jepsen.control/expand-path [String -> String])
|
||||
|
||||
@@ -234,7 +235,7 @@
|
||||
(->> (:nodes config)
|
||||
(reduce (t/fn [m :- (t/Map Key (t/Vec Node))
|
||||
[node pub-key] :- '[Node Key]]
|
||||
(assoc m pub-key (conj (get m pub-key []) node)))
|
||||
(assoc m pub-key (conj (get m pub-key []) node)))
|
||||
{})))
|
||||
|
||||
(t/ann ^:no-check byzantine-validators [Config -> (t/Coll Validator)])
|
||||
@@ -248,7 +249,6 @@
|
||||
(map key)
|
||||
(keep (tmfn (:validators config) Key Validator))))
|
||||
|
||||
|
||||
(t/ann initial-validator-votes [Config -> (t/Map Key Long)])
|
||||
(defn initial-validator-votes
|
||||
"Takes a config. Computes a map of validator public keys to votes. When there
|
||||
@@ -312,9 +312,9 @@
|
||||
(let [base-votes (zipmap (remove #{b} (keys (:validators config)))
|
||||
(repeat 2))
|
||||
byz-votes {b (conform-long
|
||||
(if (:super-byzantine-validators config)
|
||||
(dec (* 4 (dec n)))
|
||||
(- n 2)))}]
|
||||
(if (:super-byzantine-validators config)
|
||||
(dec (* 4 (dec n)))
|
||||
(- n 2)))}]
|
||||
(t/ann-form base-votes (t/Map Key Long))
|
||||
(merge base-votes byz-votes))))
|
||||
|
||||
@@ -343,9 +343,9 @@
|
||||
map."
|
||||
[]
|
||||
(conform-gen-validator
|
||||
(c/cd base-dir
|
||||
(-> (c/exec "./tendermint" :--home base-dir :gen_validator)
|
||||
(json/parse-string true)))))
|
||||
(c/cd base-dir
|
||||
(-> (c/exec "./tendermint" :--home base-dir :gen_validator)
|
||||
(json/parse-string true)))))
|
||||
|
||||
(t/ann augment-gen-validator [GenValidator -> Validator])
|
||||
(defn augment-gen-validator
|
||||
@@ -360,7 +360,7 @@
|
||||
:validators (t/Map Key Validator)
|
||||
:super-byzantine-validators Boolean
|
||||
:max-byzantine-vote-fraction Number})
|
||||
-> Config])
|
||||
-> Config])
|
||||
(defn config
|
||||
"There are two pieces of state we need to handle. The first is the validator
|
||||
set, as known to the cluster, which maps public keys to maps like:
|
||||
@@ -443,8 +443,8 @@
|
||||
(let [pub-key (:pub_key validator)
|
||||
name (->> (:nodes config)
|
||||
(filter
|
||||
(t/fn [[_ v] :- '[t/Any Key]]
|
||||
(= v pub-key)))
|
||||
(t/fn [[_ v] :- '[t/Any Key]]
|
||||
(= v pub-key)))
|
||||
first)
|
||||
_ (assert name)
|
||||
name (key name)]
|
||||
@@ -494,8 +494,6 @@
|
||||
:nodes (map-vals compact-key (:nodes c))
|
||||
:max-byzantine-vote-fraction (:max-byzantine-vote-fraction c)})
|
||||
|
||||
|
||||
|
||||
(t/ann vote-fractions [Config -> (t/Map Key Number)])
|
||||
(defn vote-fractions
|
||||
"A map of validator public keys to the fraction of the vote they control."
|
||||
@@ -575,8 +573,8 @@
|
||||
[config]
|
||||
(< ghost-limit
|
||||
(count
|
||||
(set/difference (set (keys (:validators config)))
|
||||
(set (vals (:nodes config)))))))
|
||||
(set/difference (set (keys (:validators config)))
|
||||
(set (vals (:nodes config)))))))
|
||||
|
||||
(t/ann zombie-limit Long)
|
||||
(def zombie-limit
|
||||
@@ -591,8 +589,8 @@
|
||||
[config]
|
||||
(< zombie-limit
|
||||
(count
|
||||
(remove (set (keys (:validators config)))
|
||||
(vals (:nodes config))))))
|
||||
(remove (set (keys (:validators config)))
|
||||
(vals (:nodes config))))))
|
||||
|
||||
(t/ann quorum Number)
|
||||
(def quorum
|
||||
@@ -623,7 +621,6 @@
|
||||
(set (ghost-validators config)))))
|
||||
(total-votes config))))
|
||||
|
||||
|
||||
(t/ann assert-valid [Config -> Config])
|
||||
(defn assert-valid
|
||||
"Ensures that the given config is valid, and returns it. Throws
|
||||
@@ -659,57 +656,59 @@
|
||||
state."
|
||||
[config transition]
|
||||
(assert-valid
|
||||
(case (:type transition)
|
||||
:create config
|
||||
:destroy config
|
||||
:add (let [v (:validator transition)]
|
||||
(assert (not (get-in config [:validators (:pub_key v)])))
|
||||
(assoc config :prospective-validators
|
||||
(assoc (:prospective-validators config)
|
||||
(:pub_key v) v)))
|
||||
:remove config
|
||||
:alter-votes config)))
|
||||
(case (:type transition)
|
||||
:create config
|
||||
:destroy config
|
||||
:add (let [v (:validator transition)]
|
||||
(assert (not (get-in config [:validators (:pub_key v)])))
|
||||
(assoc config :prospective-validators
|
||||
(assoc (:prospective-validators config)
|
||||
(:pub_key v) v)))
|
||||
:remove config
|
||||
:alter-votes config)))
|
||||
|
||||
(t/ann post-step [Config Transition -> Config])
|
||||
(defn post-step
|
||||
"Complete a transition once we know it's been executed."
|
||||
[config transition]
|
||||
(assert-valid
|
||||
(case (:type transition)
|
||||
(case (:type transition)
|
||||
; Create a new validator on a node
|
||||
:create (let [n (:node transition)
|
||||
v (:validator transition)]
|
||||
(assert (not (get-in config [:nodes n])))
|
||||
(assoc config :nodes (assoc (:nodes config) n (:pub_key v))))
|
||||
:create (let [n (:node transition)
|
||||
v (:validator transition)]
|
||||
(assert (not (get-in config [:nodes n])))
|
||||
(assoc config :nodes (assoc (:nodes config) n (:pub_key v))))
|
||||
|
||||
; Destroy a validator on a node
|
||||
:destroy (assoc config :nodes (dissoc (:nodes config)
|
||||
(:node transition)))
|
||||
:destroy (assoc config :nodes (dissoc (:nodes config)
|
||||
(:node transition)))
|
||||
|
||||
|
||||
; Add a validator to the validator set
|
||||
:add (let [v (:validator transition)]
|
||||
(assert (not (get-in config [:validators (:pub_key v)])))
|
||||
(-> config
|
||||
(assoc :prospective-validators
|
||||
(dissoc (:prospective-validators config)
|
||||
(:pub_key v)))
|
||||
(assoc :validators
|
||||
(assoc (:validators config) (:pub_key v) v))))
|
||||
|
||||
|
||||
:add (let [v (:validator transition)]
|
||||
(assert (not (get-in config [:validators (:pub_key v)])))
|
||||
(-> config
|
||||
(assoc :prospective-validators
|
||||
(dissoc (:prospective-validators config)
|
||||
(:pub_key v)))
|
||||
(assoc :validators
|
||||
(assoc (:validators config) (:pub_key v) v))))
|
||||
|
||||
; Remove a validator from the validator set
|
||||
:remove (assoc config :validators
|
||||
(dissoc (:validators config) (:pub_key transition)))
|
||||
:remove (assoc config :validators
|
||||
(dissoc (:validators config) (:pub_key transition)))
|
||||
|
||||
; Change the votes allocated to a validator
|
||||
:alter-votes (let [k (:pub_key transition)
|
||||
v (:votes transition)
|
||||
validators (:validators config)
|
||||
validator (get validators k)
|
||||
_ (assert validator)
|
||||
validator' (assoc validator :votes v)
|
||||
validators' (assoc validators k validator')]
|
||||
(assoc config :validators validators')))))
|
||||
:alter-votes (let [k (:pub_key transition)
|
||||
v (:votes transition)
|
||||
validators (:validators config)
|
||||
validator (get validators k)
|
||||
_ (assert validator)
|
||||
validator' (assoc validator :votes v)
|
||||
validators' (assoc validators k validator')]
|
||||
(assoc config :validators validators')))))
|
||||
|
||||
(t/ann step [Config Transition -> Config])
|
||||
(defn step
|
||||
@@ -843,9 +842,9 @@
|
||||
k (or (validator-by-short-key config short-key)
|
||||
(prospective-validator-by-short-key config short-key)
|
||||
(throw (IllegalStateException.
|
||||
(str "Don't recognize cluster validator "
|
||||
(pr-str v)
|
||||
"; where did it come from?"))))]
|
||||
(str "Don't recognize cluster validator "
|
||||
(pr-str v)
|
||||
"; where did it come from?"))))]
|
||||
[(:pub_key k) (:power v)])))
|
||||
(into {})))
|
||||
|
||||
@@ -879,8 +878,8 @@
|
||||
(let [prospective (:prospective-validators config)
|
||||
validator (get prospective k)
|
||||
_ (assert validator
|
||||
(str "Don't recognize validator "
|
||||
k "; where did it come from?"))
|
||||
(str "Don't recognize validator "
|
||||
k "; where did it come from?"))
|
||||
validator (assoc validator :votes v)
|
||||
validators (assoc validators k validator)
|
||||
prospective (dissoc prospective k)]
|
||||
@@ -900,7 +899,7 @@
|
||||
(let [local-config @(:validator-config test)
|
||||
cluster-config (tc/validator-set node)
|
||||
votes (tendermint-validator-set->vote-map
|
||||
local-config cluster-config)]
|
||||
local-config cluster-config)]
|
||||
(-> local-config
|
||||
(clear-removed-nodes votes)
|
||||
(update-known-nodes votes)
|
||||
@@ -908,39 +907,37 @@
|
||||
|
||||
(t/tc-ignore
|
||||
|
||||
(defn refresh-config!
|
||||
"Attempts to update the test's config with new information from the cluster.
|
||||
(defn refresh-config!
|
||||
"Attempts to update the test's config with new information from the cluster.
|
||||
Returns our estimate of the current config. Not threadsafe."
|
||||
[test]
|
||||
[test]
|
||||
; TODO: make this threadsafe
|
||||
(or (reduce (fn [_ node]
|
||||
(try
|
||||
(when-let [c (current-config test node)]
|
||||
(reset! (:validator-config test) c)
|
||||
(reduced c))
|
||||
(catch java.io.IOException e
|
||||
(or (reduce (fn [_ node]
|
||||
(try
|
||||
(when-let [c (current-config test node)]
|
||||
(reset! (:validator-config test) c)
|
||||
(reduced c))
|
||||
(catch java.io.IOException e
|
||||
; (info e "unable to fetch current validator set config")
|
||||
nil)))
|
||||
nil
|
||||
(shuffle (:nodes test)))
|
||||
@(:validator-config test)))
|
||||
nil)))
|
||||
nil
|
||||
(shuffle (:nodes test)))
|
||||
@(:validator-config test)))
|
||||
|
||||
(defn generator
|
||||
"A generator of legal state transitions on the current validator state."
|
||||
[]
|
||||
(reify gen/Generator
|
||||
(op [this test process]
|
||||
(try
|
||||
(info "refreshing config")
|
||||
(let [config (refresh-config! test)]
|
||||
(info :config-refreshed)
|
||||
(info (with-out-str (pprint config)))
|
||||
(info (with-out-str (pprint (compact-config config))))
|
||||
{:type :info
|
||||
:f :transition
|
||||
:value (rand-legal-transition test config)})
|
||||
(catch Exception e
|
||||
(warn e "error generating transition")
|
||||
(throw e))))))
|
||||
|
||||
)
|
||||
(defn generator
|
||||
"A generator of legal state transitions on the current validator state."
|
||||
[]
|
||||
(reify gen/Generator
|
||||
(op [this test process]
|
||||
(try
|
||||
(info "refreshing config")
|
||||
(let [config (refresh-config! test)]
|
||||
(info :config-refreshed)
|
||||
(info (with-out-str (pprint config)))
|
||||
(info (with-out-str (pprint (compact-config config))))
|
||||
{:type :info
|
||||
:f :transition
|
||||
:value (rand-legal-transition test config)})
|
||||
(catch Exception e
|
||||
(warn e "error generating transition")
|
||||
(throw e)))))))
|
||||
|
||||
Reference in New Issue
Block a user