mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-11 23:32:50 +00:00
Compare commits
21 Commits
wb/abc-cli
...
sergio/hid
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff8fd2731d | ||
|
|
05dd2f8519 | ||
|
|
85870def7b | ||
|
|
ff2758b32e | ||
|
|
a82cb7dcda | ||
|
|
1dfb3451ea | ||
|
|
9f13b9b083 | ||
|
|
16ba782fa6 | ||
|
|
474ed04273 | ||
|
|
2d8287d0f7 | ||
|
|
294a9695b4 | ||
|
|
849461aab2 | ||
|
|
8ba6d218e4 | ||
|
|
0f8932f4ef | ||
|
|
73ef2675ce | ||
|
|
e0c6199aae | ||
|
|
0c05841902 | ||
|
|
4023580a25 | ||
|
|
2db1e422d8 | ||
|
|
093961ae2d | ||
|
|
d030cddca0 |
@@ -6,6 +6,7 @@ linters:
|
||||
- dogsled
|
||||
- dupl
|
||||
- errcheck
|
||||
- exportloopref
|
||||
# - funlen
|
||||
# - gochecknoglobals
|
||||
# - gochecknoinits
|
||||
@@ -26,7 +27,7 @@ linters:
|
||||
# - maligned
|
||||
- nakedret
|
||||
- prealloc
|
||||
- scopelint
|
||||
# - scopelint
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- stylecheck
|
||||
|
||||
147
CHANGELOG.md
147
CHANGELOG.md
@@ -1,11 +1,40 @@
|
||||
# Changelog
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/cosmos).
|
||||
|
||||
## v0.34.14
|
||||
|
||||
This release backports the `rollback` feature to allow recovery in the event of an incorrect app hash.
|
||||
|
||||
### FEATURES
|
||||
|
||||
- [\#6982](https://github.com/tendermint/tendermint/pull/6982) The tendermint binary now has built-in suppport for running the end-to-end test application (with state sync support) (@cmwaters).
|
||||
- [cli] [#7033](https://github.com/tendermint/tendermint/pull/7033) Add a `rollback` command to rollback to the previous tendermint state. This may be useful in the event of non-determinstic app hash or when reverting an upgrade. @cmwaters
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
- [\#7103](https://github.com/tendermint/tendermint/pull/7104) Remove IAVL dependency (backport of #6550) (@cmwaters)
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [\#7057](https://github.com/tendermint/tendermint/pull/7057) Import Postgres driver support for the psql indexer (@creachadair).
|
||||
- [ABCI] [\#7110](https://github.com/tendermint/tendermint/issues/7110) Revert "change client to use multi-reader mutexes (#6873)" (@tychoish).
|
||||
|
||||
## v0.34.13
|
||||
|
||||
This release backports improvements to state synchronization and ABCI
|
||||
performance under concurrent load, and the PostgreSQL event indexer.
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
- [statesync] [\#6881](https://github.com/tendermint/tendermint/issues/6881) improvements to stateprovider logic (@cmwaters)
|
||||
- [ABCI] [\#6873](https://github.com/tendermint/tendermint/issues/6873) change client to use multi-reader mutexes (@tychoish)
|
||||
- [indexing] [\#6906](https://github.com/tendermint/tendermint/issues/6906) enable the PostgreSQL indexer sink (@creachadair)
|
||||
|
||||
## v0.34.12
|
||||
|
||||
Special thanks to external contributors on this release: @JayT106.
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES
|
||||
|
||||
- [rpc] [\#6717](https://github.com/tendermint/tendermint/pull/6717) introduce
|
||||
@@ -28,8 +57,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
This release improves the robustness of statesync; tweaking channel priorities and timeouts and
|
||||
adding two new parameters to the state sync config.
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Apps
|
||||
@@ -53,8 +80,6 @@ This release fixes a bug where peers would sometimes try to send messages
|
||||
on incorrect channels. Special thanks to our friends at Oasis Labs for surfacing
|
||||
this issue!
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
- [p2p/node] [\#6339](https://github.com/tendermint/tendermint/issues/6339) Fix bug with using custom channels (@cmwaters)
|
||||
- [light] [\#6346](https://github.com/tendermint/tendermint/issues/6346) Correctly handle too high errors to improve client robustness (@cmwaters)
|
||||
|
||||
@@ -70,8 +95,6 @@ This release also includes a small Go API-breaking change, to reduce panics in t
|
||||
|
||||
Special thanks to our external contributors on this release: @gchaincl
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Go API
|
||||
@@ -94,8 +117,6 @@ Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermi
|
||||
This release, in conjunction with [a fix in the Cosmos SDK](https://github.com/cosmos/cosmos-sdk/pull/8641),
|
||||
introduces changes that should mean the logs are much, much quieter. 🎉
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
- [libs/log] [\#6174](https://github.com/tendermint/tendermint/issues/6174) Include timestamp (`ts` field; `time.RFC3339Nano` format) in JSON logger output (@melekes)
|
||||
@@ -133,8 +154,6 @@ use remote signer implementations instead of `FilePV` in production.
|
||||
Thank you to @joe-bowman for his assistance with this vulnerability and a particular
|
||||
shout-out to @marbar3778 for diagnosing it quickly.
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [consensus] [\#6128](https://github.com/tendermint/tendermint/pull/6128) Remove privValidator from log call (@tessr)
|
||||
@@ -155,8 +174,6 @@ Thank you to our friends at Crypto.com for the initial report of this memory lea
|
||||
|
||||
Special thanks to other external contributors on this release: @yayajacky, @odidev, @laniehei, and @c29r3!
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [light] [\#6022](https://github.com/tendermint/tendermint/pull/6022) Fix a bug when the number of validators equals 100 (@melekes)
|
||||
@@ -176,8 +193,6 @@ or https://nvd.nist.gov/vuln/detail/CVE-2021-21271.
|
||||
Tendermint Core v0.34.3 also updates GoGo Protobuf to 1.3.2 in order to pick up the fix for
|
||||
https://nvd.nist.gov/vuln/detail/CVE-2021-3121.
|
||||
|
||||
Friendly reminder: We have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
- [evidence] [[security fix]](https://github.com/tendermint/tendermint/security/advisories/GHSA-p658-8693-mhvg) Use correct source of evidence time (@cmwaters)
|
||||
@@ -191,8 +206,6 @@ This release fixes a substantial bug in evidence handling where evidence could
|
||||
sometimes be broadcast before the block containing that evidence was fully committed,
|
||||
resulting in some nodes panicking when trying to verify said evidence.
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- Go API
|
||||
@@ -216,8 +229,6 @@ disconnecting from this node. As a temporary remedy (until the mempool package
|
||||
is refactored), the `max-batch-bytes` was disabled. Transactions will be sent
|
||||
one by one without batching.
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- CLI/RPC/Config
|
||||
@@ -246,8 +257,6 @@ Holy smokes, this is a big one! For a more reader-friendly overview of the chang
|
||||
Special thanks to external contributors on this release: @james-ray, @fedekunze, @favadi, @alessio,
|
||||
@joe-bowman, @cuonglm, @SadPencil and @dongsam.
|
||||
|
||||
And as always, friendly reminder, that we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
- CLI/RPC/Config
|
||||
@@ -488,9 +497,6 @@ as 2/3+ of the signatures are checked._
|
||||
|
||||
Special thanks to @njmurarka at Bluzelle Networks for reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [consensus] Do not allow signatures for a wrong block in commits (@ebuchman)
|
||||
@@ -506,8 +512,6 @@ need to update your code.**
|
||||
|
||||
Special thanks to external contributors on this release: @tau3,
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -567,8 +571,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
|
||||
Special thanks to external contributors on this release: @whylee259, @greg-szabo
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -655,9 +657,6 @@ Notes:
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for finding
|
||||
and reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [mempool] Reserve IDs in InitPeer instead of AddPeer (@tessr)
|
||||
@@ -670,8 +669,6 @@ program](https://hackerone.com/tendermint).
|
||||
Special thanks to external contributors on this release:
|
||||
@antho1404, @michaelfig, @gterzian, @tau3, @Shivani912
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- CLI/RPC/Config
|
||||
@@ -722,9 +719,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
Special thanks to external contributors on this release:
|
||||
@princesinha19
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES:
|
||||
|
||||
- [rpc] [\#3333](https://github.com/tendermint/tendermint/issues/3333) Add `order_by` to `/tx_search` endpoint, allowing to change default ordering from asc to desc (@princesinha19)
|
||||
@@ -743,9 +737,6 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
Special thanks to external contributors on this release: @mrekucci, @PSalant726, @princesinha19, @greg-szabo, @dongsam, @cuonglm, @jgimeno, @yenkhoon
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program.](https://hackerone.com/tendermint).
|
||||
|
||||
*January 14, 2020*
|
||||
|
||||
This release contains breaking changes to the `Block#Header`, specifically
|
||||
@@ -974,9 +965,6 @@ Notes:
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for finding
|
||||
and reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [mempool] Reserve IDs in InitPeer instead of AddPeer (@tessr)
|
||||
@@ -988,9 +976,6 @@ _January, 9, 2020_
|
||||
|
||||
Special thanks to external contributors on this release: @greg-szabo, @gregzaitsev, @yenkhoon
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES:
|
||||
|
||||
- [rpc/lib] [\#4248](https://github.com/tendermint/tendermint/issues/4248) RPC client basic authentication support (@greg-szabo)
|
||||
@@ -1012,9 +997,6 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
Special thanks to external contributors on this release: @erikgrinaker, @guagualvcha, @hsyis, @cosmostuba, @whunmr, @austinabell
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program.](https://hackerone.com/tendermint).
|
||||
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
@@ -1054,9 +1036,6 @@ identified and fixed here.
|
||||
Special thanks to [elvishacker](https://hackerone.com/elvishacker) for finding
|
||||
and reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -1083,9 +1062,6 @@ accepting new peers and only allowing `ed25519` pubkeys.
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for pointing
|
||||
this out.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Only allow ed25519 pubkeys when connecting
|
||||
@@ -1101,9 +1077,6 @@ All clients are recommended to upgrade. See
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for discovering
|
||||
and reporting this issue.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Fix for panic on nil public key send to a peer
|
||||
@@ -1114,9 +1087,6 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
Special thanks to external contributors on this release: @jon-certik, @gracenoah, @PSalant726, @gchaincl
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- CLI/RPC/Config
|
||||
@@ -1152,9 +1122,6 @@ guide.
|
||||
Special thanks to external contributors on this release:
|
||||
@gchaincl, @bluele, @climber73
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
- [consensus] [\#3839](https://github.com/tendermint/tendermint/issues/3839) Reduce "Error attempting to add vote" message severity (Error -> Info)
|
||||
@@ -1175,9 +1142,6 @@ program](https://hackerone.com/tendermint).
|
||||
Special thanks to external contributors on this release:
|
||||
@ruseinov, @bluele, @guagualvcha
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -1217,9 +1181,6 @@ This release contains a minor enhancement to the ABCI and some breaking changes
|
||||
- CheckTx requests include a `CheckTxType` enum that can be set to `Recheck` to indicate to the application that this transaction was already checked/validated and certain expensive operations (like checking signatures) can be skipped
|
||||
- Removed various functions from `libs` pkgs
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -1265,9 +1226,6 @@ and the RPC, namely:
|
||||
[docs](https://github.com/tendermint/tendermint/blob/60827f75623b92eff132dc0eff5b49d2025c591e/docs/spec/abci/abci.md#events)
|
||||
- Bind RPC to localhost by default, not to the public interface [UPGRADING/RPC_Changes](./UPGRADING.md#rpc_changes)
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
* CLI/RPC/Config
|
||||
@@ -1368,9 +1326,6 @@ Notes:
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for finding
|
||||
and reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [mempool] Reserve IDs in InitPeer instead of AddPeer (@tessr)
|
||||
@@ -1390,9 +1345,6 @@ identified and fixed here.
|
||||
Special thanks to [elvishacker](https://hackerone.com/elvishacker) for finding
|
||||
and reporting this.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
- Go API
|
||||
@@ -1419,9 +1371,6 @@ accepting new peers and only allowing `ed25519` pubkeys.
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for pointing
|
||||
this out.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Only allow ed25519 pubkeys when connecting
|
||||
@@ -1437,9 +1386,6 @@ All clients are recommended to upgrade. See
|
||||
Special thanks to [fudongbai](https://hackerone.com/fudongbai) for discovering
|
||||
and reporting this issue.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### SECURITY:
|
||||
|
||||
- [p2p] [\#4030](https://github.com/tendermint/tendermint/issues/4030) Fix for panic on nil public key send to a peer
|
||||
@@ -1734,9 +1680,6 @@ See the [v0.31.0
|
||||
Milestone](https://github.com/tendermint/tendermint/milestone/19?closed=1) for
|
||||
more details.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
* CLI/RPC/Config
|
||||
@@ -1867,7 +1810,7 @@ For more, see issues marked
|
||||
|
||||
This release also includes a fix to prevent Tendermint from including the same
|
||||
piece of evidence in more than one block. This issue was reported by @chengwenxi in our
|
||||
[bug bounty program](https://hackerone.com/tendermint).
|
||||
[bug bounty program](https://hackerone.com/cosmos).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
@@ -1956,9 +1899,6 @@ This release contains two important fixes: one for p2p layer where we sometimes
|
||||
were not closing connections and one for consensus layer where consensus with
|
||||
no empty blocks (`create_empty_blocks = false`) could halt.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS:
|
||||
- [pex] [\#3037](https://github.com/tendermint/tendermint/issues/3037) Only log "Reached max attempts to dial" once
|
||||
- [rpc] [\#3159](https://github.com/tendermint/tendermint/issues/3159) Expose
|
||||
@@ -1997,9 +1937,6 @@ While we are trying to stabilize the Block protocol to preserve compatibility
|
||||
with old chains, there may be some final changes yet to come before Cosmos
|
||||
launch as we continue to audit and test the software.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
* CLI/RPC/Config
|
||||
@@ -2047,9 +1984,6 @@ program](https://hackerone.com/tendermint).
|
||||
Special thanks to external contributors on this release:
|
||||
@HaoyangLiu
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BUG FIXES:
|
||||
- [consensus] Fix consensus halt from proposing blocks with too much evidence
|
||||
|
||||
@@ -2177,9 +2111,6 @@ Special thanks to @dlguddus for discovering a [major
|
||||
issue](https://github.com/tendermint/tendermint/issues/2718#issuecomment-440888677)
|
||||
in the proposer selection algorithm.
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
This release is primarily about fixes to the proposer selection algorithm
|
||||
in preparation for the [Cosmos Game of
|
||||
Stakes](https://blog.cosmos.network/the-game-of-stakes-is-open-for-registration-83a404746ee6).
|
||||
@@ -2241,9 +2172,6 @@ Special thanks to external contributors on this release:
|
||||
@ackratos, @goolAdapter, @james-ray, @joe-bowman, @kostko,
|
||||
@nagarajmanjunath, @tomtau
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES:
|
||||
|
||||
- [rpc] [\#2747](https://github.com/tendermint/tendermint/issues/2747) Enable subscription to tags emitted from `BeginBlock`/`EndBlock` (@kostko)
|
||||
@@ -2282,9 +2210,6 @@ program](https://hackerone.com/tendermint).
|
||||
Special thanks to external contributors on this release:
|
||||
@danil-lashin, @kevlubkcm, @krhubert, @srmo
|
||||
|
||||
Friendly reminder, we have a [bug bounty
|
||||
program](https://hackerone.com/tendermint).
|
||||
|
||||
### BREAKING CHANGES:
|
||||
|
||||
* Go API
|
||||
@@ -2328,8 +2253,6 @@ program](https://hackerone.com/tendermint).
|
||||
|
||||
Special thanks to external contributors on this release: @hleb-albau, @zhuzeyu
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### FEATURES:
|
||||
|
||||
- [rpc] [\#2582](https://github.com/tendermint/tendermint/issues/2582) Enable CORS on RPC API (@hleb-albau)
|
||||
@@ -2347,8 +2270,6 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
|
||||
Special thanks to external contributors on this release: @katakonst
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
### IMPROVEMENTS:
|
||||
|
||||
- [consensus] [\#2704](https://github.com/tendermint/tendermint/issues/2704) Simplify valid POL round logic
|
||||
@@ -2376,7 +2297,7 @@ Special thanks to external contributors on this release:
|
||||
@james-ray, @overbool, @phymbert, @Slamper, @Uzair1995, @yutianwu.
|
||||
|
||||
Special thanks to @Slamper for a series of bug reports in our [bug bounty
|
||||
program](https://hackerone.com/tendermint) which are fixed in this release.
|
||||
program](https://hackerone.com/cosmos) which are fixed in this release.
|
||||
|
||||
This release is primarily about adding Version fields to various data structures,
|
||||
optimizing consensus messages for signing and verification in
|
||||
@@ -2522,8 +2443,6 @@ It also addresses some issues found via security audit, removes various unused
|
||||
functions from `libs/common`, and implements
|
||||
[ADR-012](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-012-peer-transport.md).
|
||||
|
||||
Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermint).
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
||||
* CLI/RPC/Config
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Unreleased Changes
|
||||
|
||||
## v0.34.13
|
||||
## v0.34.15
|
||||
|
||||
Special thanks to external contributors on this release:
|
||||
|
||||
@@ -22,5 +22,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
|
||||
|
||||
### IMPROVEMENTS
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
### BUG FIXES
|
||||
- [\#7057](https://github.com/tendermint/tendermint/pull/7057) Import Postgres driver support for the psql indexer (@creachadair).
|
||||
- [\#7106](https://github.com/tendermint/tendermint/pull/7106) Revert mutex change to ABCI Clients (@tychoish).
|
||||
|
||||
@@ -20,6 +20,12 @@ type localClient struct {
|
||||
Callback
|
||||
}
|
||||
|
||||
var _ Client = (*localClient)(nil)
|
||||
|
||||
// NewLocalClient creates a local client, which will be directly calling the
|
||||
// methods of the given app.
|
||||
//
|
||||
// Both Async and Sync methods ignore the given context.Context parameter.
|
||||
func NewLocalClient(mtx *tmsync.Mutex, app types.Application) Client {
|
||||
if mtx == nil {
|
||||
mtx = new(tmsync.Mutex)
|
||||
|
||||
@@ -761,9 +761,12 @@ func (m *RequestQuery) GetProve() bool {
|
||||
|
||||
type RequestBeginBlock struct {
|
||||
Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
|
||||
Header types1.Header `protobuf:"bytes,2,opt,name=header,proto3" json:"header"`
|
||||
LastCommitInfo LastCommitInfo `protobuf:"bytes,3,opt,name=last_commit_info,json=lastCommitInfo,proto3" json:"last_commit_info"`
|
||||
ByzantineValidators []Evidence `protobuf:"bytes,4,rep,name=byzantine_validators,json=byzantineValidators,proto3" json:"byzantine_validators"`
|
||||
Height int64 `protobuf:"varint,5,opt,name=height,proto3" json:"height,omitempty"`
|
||||
Time time.Time `protobuf:"bytes,6,opt,name=time,proto3,stdtime" json:"time"`
|
||||
NextValidatorsHash []byte `protobuf:"bytes,7,opt,name=next_validators_hash,json=nextValidatorsHash,proto3" json:"next_validators_hash,omitempty"`
|
||||
ProposerAddress []byte `protobuf:"bytes,8,opt,name=proposer_address,json=proposerAddress,proto3" json:"proposer_address,omitempty"`
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) Reset() { *m = RequestBeginBlock{} }
|
||||
@@ -806,13 +809,6 @@ func (m *RequestBeginBlock) GetHash() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetHeader() types1.Header {
|
||||
if m != nil {
|
||||
return m.Header
|
||||
}
|
||||
return types1.Header{}
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetLastCommitInfo() LastCommitInfo {
|
||||
if m != nil {
|
||||
return m.LastCommitInfo
|
||||
@@ -827,6 +823,34 @@ func (m *RequestBeginBlock) GetByzantineValidators() []Evidence {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetHeight() int64 {
|
||||
if m != nil {
|
||||
return m.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetTime() time.Time {
|
||||
if m != nil {
|
||||
return m.Time
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetNextValidatorsHash() []byte {
|
||||
if m != nil {
|
||||
return m.NextValidatorsHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RequestBeginBlock) GetProposerAddress() []byte {
|
||||
if m != nil {
|
||||
return m.ProposerAddress
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RequestCheckTx struct {
|
||||
Tx []byte `protobuf:"bytes,1,opt,name=tx,proto3" json:"tx,omitempty"`
|
||||
Type CheckTxType `protobuf:"varint,2,opt,name=type,proto3,enum=tendermint.abci.CheckTxType" json:"type,omitempty"`
|
||||
@@ -3199,179 +3223,181 @@ func init() {
|
||||
func init() { proto.RegisterFile("tendermint/abci/types.proto", fileDescriptor_252557cfdd89a31a) }
|
||||
|
||||
var fileDescriptor_252557cfdd89a31a = []byte{
|
||||
// 2741 bytes of a gzipped FileDescriptorProto
|
||||
// 2769 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x5a, 0x4b, 0x73, 0x1b, 0xc7,
|
||||
0x11, 0xc6, 0xfb, 0xd1, 0x24, 0x1e, 0x1c, 0xd1, 0x12, 0xb4, 0x92, 0x48, 0x79, 0x55, 0x72, 0x2c,
|
||||
0xd9, 0x26, 0x63, 0xaa, 0xa4, 0x48, 0xb1, 0x13, 0x9b, 0x80, 0x20, 0x83, 0x26, 0x4d, 0x30, 0x4b,
|
||||
0x48, 0xce, 0xcb, 0x5a, 0x2f, 0xb0, 0x43, 0x60, 0x2d, 0x60, 0x77, 0x8d, 0x1d, 0x50, 0xa4, 0x8f,
|
||||
0x71, 0x72, 0x51, 0x2e, 0xce, 0x2d, 0x17, 0xff, 0x8f, 0x9c, 0x72, 0xc9, 0xc5, 0x55, 0xb9, 0xf8,
|
||||
0x98, 0x93, 0x93, 0x92, 0x2a, 0x97, 0xfc, 0x81, 0x9c, 0x52, 0x49, 0xcd, 0x63, 0x5f, 0x00, 0x16,
|
||||
0x00, 0xed, 0xdc, 0x7c, 0x9b, 0x99, 0xed, 0xee, 0xc5, 0xf4, 0x4e, 0x7f, 0xfd, 0x75, 0x0f, 0xe0,
|
||||
0x12, 0xc1, 0xa6, 0x8e, 0x87, 0x03, 0xc3, 0x24, 0x9b, 0x5a, 0xbb, 0x63, 0x6c, 0x92, 0x53, 0x1b,
|
||||
0x3b, 0x1b, 0xf6, 0xd0, 0x22, 0x16, 0x2a, 0xf9, 0x0f, 0x37, 0xe8, 0x43, 0xe9, 0x4a, 0x40, 0xba,
|
||||
0x33, 0x3c, 0xb5, 0x89, 0xb5, 0x69, 0x0f, 0x2d, 0xeb, 0x88, 0xcb, 0x4b, 0x97, 0x03, 0x8f, 0x99,
|
||||
0x9d, 0xa0, 0xb5, 0xd0, 0x53, 0xa1, 0xfc, 0x04, 0x9f, 0xba, 0x4f, 0xaf, 0x4c, 0xe8, 0xda, 0xda,
|
||||
0x50, 0x1b, 0xb8, 0x8f, 0xd7, 0xbb, 0x96, 0xd5, 0xed, 0xe3, 0x4d, 0x36, 0x6b, 0x8f, 0x8e, 0x36,
|
||||
0x89, 0x31, 0xc0, 0x0e, 0xd1, 0x06, 0xb6, 0x10, 0x58, 0xed, 0x5a, 0x5d, 0x8b, 0x0d, 0x37, 0xe9,
|
||||
0x88, 0xaf, 0xca, 0x7f, 0xc8, 0x41, 0x56, 0xc1, 0x9f, 0x8e, 0xb0, 0x43, 0xd0, 0x16, 0xa4, 0x70,
|
||||
0xa7, 0x67, 0x55, 0xe2, 0x57, 0xe3, 0xaf, 0x2e, 0x6d, 0x5d, 0xde, 0x18, 0xdb, 0xdc, 0x86, 0x90,
|
||||
0xab, 0x77, 0x7a, 0x56, 0x23, 0xa6, 0x30, 0x59, 0x74, 0x1b, 0xd2, 0x47, 0xfd, 0x91, 0xd3, 0xab,
|
||||
0x24, 0x98, 0xd2, 0x95, 0x28, 0xa5, 0x07, 0x54, 0xa8, 0x11, 0x53, 0xb8, 0x34, 0x7d, 0x95, 0x61,
|
||||
0x1e, 0x59, 0x95, 0xe4, 0xec, 0x57, 0xed, 0x98, 0x47, 0xec, 0x55, 0x54, 0x16, 0x55, 0x01, 0x1c,
|
||||
0x4c, 0x54, 0xcb, 0x26, 0x86, 0x65, 0x56, 0x52, 0x4c, 0xf3, 0xe5, 0x28, 0xcd, 0x43, 0x4c, 0x9a,
|
||||
0x4c, 0xb0, 0x11, 0x53, 0xf2, 0x8e, 0x3b, 0xa1, 0x36, 0x0c, 0xd3, 0x20, 0x6a, 0xa7, 0xa7, 0x19,
|
||||
0x66, 0x25, 0x3d, 0xdb, 0xc6, 0x8e, 0x69, 0x90, 0x1a, 0x15, 0xa4, 0x36, 0x0c, 0x77, 0x42, 0xb7,
|
||||
0xfc, 0xe9, 0x08, 0x0f, 0x4f, 0x2b, 0x99, 0xd9, 0x5b, 0xfe, 0x19, 0x15, 0xa2, 0x5b, 0x66, 0xd2,
|
||||
0xa8, 0x0e, 0x4b, 0x6d, 0xdc, 0x35, 0x4c, 0xb5, 0xdd, 0xb7, 0x3a, 0x4f, 0x2a, 0x59, 0xa6, 0x2c,
|
||||
0x47, 0x29, 0x57, 0xa9, 0x68, 0x95, 0x4a, 0x36, 0x62, 0x0a, 0xb4, 0xbd, 0x19, 0x7a, 0x1b, 0x72,
|
||||
0x9d, 0x1e, 0xee, 0x3c, 0x51, 0xc9, 0x49, 0x25, 0xc7, 0x6c, 0xac, 0x47, 0xd9, 0xa8, 0x51, 0xb9,
|
||||
0xd6, 0x49, 0x23, 0xa6, 0x64, 0x3b, 0x7c, 0x48, 0xf7, 0xaf, 0xe3, 0xbe, 0x71, 0x8c, 0x87, 0x54,
|
||||
0x3f, 0x3f, 0x7b, 0xff, 0xf7, 0xb9, 0x24, 0xb3, 0x90, 0xd7, 0xdd, 0x09, 0x7a, 0x07, 0xf2, 0xd8,
|
||||
0xd4, 0xc5, 0x36, 0x80, 0x99, 0xb8, 0x1a, 0x79, 0x56, 0x4c, 0xdd, 0xdd, 0x44, 0x0e, 0x8b, 0x31,
|
||||
0xba, 0x0b, 0x99, 0x8e, 0x35, 0x18, 0x18, 0xa4, 0xb2, 0xc4, 0xb4, 0xd7, 0x22, 0x37, 0xc0, 0xa4,
|
||||
0x1a, 0x31, 0x45, 0xc8, 0xa3, 0x7d, 0x28, 0xf6, 0x0d, 0x87, 0xa8, 0x8e, 0xa9, 0xd9, 0x4e, 0xcf,
|
||||
0x22, 0x4e, 0x65, 0x99, 0x59, 0xb8, 0x1e, 0x65, 0x61, 0xcf, 0x70, 0xc8, 0xa1, 0x2b, 0xdc, 0x88,
|
||||
0x29, 0x85, 0x7e, 0x70, 0x81, 0xda, 0xb3, 0x8e, 0x8e, 0xf0, 0xd0, 0x33, 0x58, 0x29, 0xcc, 0xb6,
|
||||
0xd7, 0xa4, 0xd2, 0xae, 0x3e, 0xb5, 0x67, 0x05, 0x17, 0xd0, 0xaf, 0xe0, 0x5c, 0xdf, 0xd2, 0x74,
|
||||
0xcf, 0x9c, 0xda, 0xe9, 0x8d, 0xcc, 0x27, 0x95, 0x22, 0x33, 0x7a, 0x23, 0xf2, 0x47, 0x5a, 0x9a,
|
||||
0xee, 0x9a, 0xa8, 0x51, 0x85, 0x46, 0x4c, 0x59, 0xe9, 0x8f, 0x2f, 0xa2, 0xc7, 0xb0, 0xaa, 0xd9,
|
||||
0x76, 0xff, 0x74, 0xdc, 0x7a, 0x89, 0x59, 0xbf, 0x19, 0x65, 0x7d, 0x9b, 0xea, 0x8c, 0x9b, 0x47,
|
||||
0xda, 0xc4, 0x6a, 0x35, 0x0b, 0xe9, 0x63, 0xad, 0x3f, 0xc2, 0xf2, 0x0f, 0x60, 0x29, 0x10, 0xea,
|
||||
0xa8, 0x02, 0xd9, 0x01, 0x76, 0x1c, 0xad, 0x8b, 0x19, 0x32, 0xe4, 0x15, 0x77, 0x2a, 0x17, 0x61,
|
||||
0x39, 0x18, 0xde, 0xf2, 0xc0, 0x53, 0xa4, 0x81, 0x4b, 0x15, 0x8f, 0xf1, 0xd0, 0xa1, 0xd1, 0x2a,
|
||||
0x14, 0xc5, 0x14, 0x5d, 0x83, 0x02, 0x3b, 0x3e, 0xaa, 0xfb, 0x9c, 0xa2, 0x47, 0x4a, 0x59, 0x66,
|
||||
0x8b, 0x8f, 0x84, 0xd0, 0x3a, 0x2c, 0xd9, 0x5b, 0xb6, 0x27, 0x92, 0x64, 0x22, 0x60, 0x6f, 0xd9,
|
||||
0x42, 0x40, 0xfe, 0x31, 0x94, 0xc7, 0xa3, 0x1d, 0x95, 0x21, 0xf9, 0x04, 0x9f, 0x8a, 0xf7, 0xd1,
|
||||
0x21, 0x5a, 0x15, 0xdb, 0x62, 0xef, 0xc8, 0x2b, 0x62, 0x8f, 0x7f, 0x4d, 0x78, 0xca, 0x5e, 0x98,
|
||||
0xa3, 0xbb, 0x90, 0xa2, 0xa8, 0x29, 0x00, 0x50, 0xda, 0xe0, 0x90, 0xba, 0xe1, 0x42, 0xea, 0x46,
|
||||
0xcb, 0x85, 0xd4, 0x6a, 0xee, 0xab, 0x6f, 0xd6, 0x63, 0x5f, 0xfc, 0x7d, 0x3d, 0xae, 0x30, 0x0d,
|
||||
0x74, 0x91, 0x46, 0xa5, 0x66, 0x98, 0xaa, 0xa1, 0x8b, 0xf7, 0x64, 0xd9, 0x7c, 0x47, 0x47, 0xbb,
|
||||
0x50, 0xee, 0x58, 0xa6, 0x83, 0x4d, 0x67, 0xe4, 0xa8, 0x1c, 0xb2, 0x05, 0xec, 0x4d, 0x46, 0x4d,
|
||||
0xcd, 0x15, 0x3c, 0x60, 0x72, 0x4a, 0xa9, 0x13, 0x5e, 0x40, 0x0f, 0x00, 0x8e, 0xb5, 0xbe, 0xa1,
|
||||
0x6b, 0xc4, 0x1a, 0x3a, 0x95, 0xd4, 0xd5, 0xe4, 0x54, 0x33, 0x8f, 0x5c, 0x91, 0x87, 0xb6, 0xae,
|
||||
0x11, 0x5c, 0x4d, 0xd1, 0x5f, 0xab, 0x04, 0x34, 0xd1, 0x2b, 0x50, 0xd2, 0x6c, 0x5b, 0x75, 0x88,
|
||||
0x46, 0xb0, 0xda, 0x3e, 0x25, 0xd8, 0x61, 0x60, 0xb8, 0xac, 0x14, 0x34, 0xdb, 0x3e, 0xa4, 0xab,
|
||||
0x55, 0xba, 0x88, 0xae, 0x43, 0x91, 0x02, 0x9f, 0xa1, 0xf5, 0xd5, 0x1e, 0x36, 0xba, 0x3d, 0xc2,
|
||||
0x40, 0x2f, 0xa9, 0x14, 0xc4, 0x6a, 0x83, 0x2d, 0xca, 0xba, 0x77, 0x10, 0x18, 0xe8, 0x21, 0x04,
|
||||
0x29, 0x5d, 0x23, 0x1a, 0x73, 0xe4, 0xb2, 0xc2, 0xc6, 0x74, 0xcd, 0xd6, 0x48, 0x4f, 0xb8, 0x87,
|
||||
0x8d, 0xd1, 0x79, 0xc8, 0x08, 0xb3, 0x49, 0x66, 0x56, 0xcc, 0xe8, 0x37, 0xb3, 0x87, 0xd6, 0x31,
|
||||
0x66, 0x28, 0x9f, 0x53, 0xf8, 0x44, 0xfe, 0x6d, 0x02, 0x56, 0x26, 0xe0, 0x91, 0xda, 0xed, 0x69,
|
||||
0x4e, 0xcf, 0x7d, 0x17, 0x1d, 0xa3, 0x3b, 0xd4, 0xae, 0xa6, 0xe3, 0xa1, 0x48, 0x4b, 0x95, 0xa0,
|
||||
0x8b, 0x78, 0xca, 0x6d, 0xb0, 0xe7, 0xc2, 0x35, 0x42, 0x1a, 0x35, 0xa1, 0xdc, 0xd7, 0x1c, 0xa2,
|
||||
0x72, 0xb8, 0x51, 0x03, 0x29, 0x6a, 0x12, 0x64, 0xf7, 0x34, 0x17, 0xa0, 0xe8, 0x61, 0x17, 0x86,
|
||||
0x8a, 0xfd, 0xd0, 0x2a, 0x52, 0x60, 0xb5, 0x7d, 0xfa, 0x99, 0x66, 0x12, 0xc3, 0xc4, 0xea, 0xc4,
|
||||
0x97, 0xbb, 0x38, 0x61, 0xb4, 0x7e, 0x6c, 0xe8, 0xd8, 0xec, 0xb8, 0x9f, 0xec, 0x9c, 0xa7, 0xec,
|
||||
0x7d, 0x52, 0x47, 0x56, 0xa0, 0x18, 0x06, 0x78, 0x54, 0x84, 0x04, 0x39, 0x11, 0x0e, 0x48, 0x90,
|
||||
0x13, 0xf4, 0x43, 0x48, 0xd1, 0x4d, 0xb2, 0xcd, 0x17, 0xa7, 0x64, 0x57, 0xa1, 0xd7, 0x3a, 0xb5,
|
||||
0xb1, 0xc2, 0x24, 0x65, 0xd9, 0x8b, 0x06, 0x0f, 0xf4, 0xc7, 0xad, 0xca, 0x37, 0xa0, 0x34, 0x86,
|
||||
0xea, 0x81, 0xef, 0x17, 0x0f, 0x7e, 0x3f, 0xb9, 0x04, 0x85, 0x10, 0x84, 0xcb, 0xe7, 0x61, 0x75,
|
||||
0x1a, 0x22, 0xcb, 0x3d, 0x6f, 0x3d, 0x84, 0xac, 0xe8, 0x36, 0xe4, 0x3c, 0x48, 0xe6, 0xd1, 0x38,
|
||||
0xe9, 0x2b, 0x57, 0x58, 0xf1, 0x44, 0x69, 0x18, 0xd2, 0x63, 0xcd, 0xce, 0x43, 0x82, 0xfd, 0xf0,
|
||||
0xac, 0x66, 0xdb, 0x0d, 0xcd, 0xe9, 0xc9, 0x1f, 0x43, 0x25, 0x0a, 0x6e, 0xc7, 0xb6, 0x91, 0xf2,
|
||||
0x8e, 0xe1, 0x79, 0xc8, 0x1c, 0x59, 0xc3, 0x81, 0x46, 0x98, 0xb1, 0x82, 0x22, 0x66, 0xf4, 0x78,
|
||||
0x72, 0xe8, 0x4d, 0xb2, 0x65, 0x3e, 0x91, 0x55, 0xb8, 0x18, 0x09, 0xb9, 0x54, 0xc5, 0x30, 0x75,
|
||||
0xcc, 0xfd, 0x59, 0x50, 0xf8, 0xc4, 0x37, 0xc4, 0x7f, 0x2c, 0x9f, 0xd0, 0xd7, 0x3a, 0x6c, 0xaf,
|
||||
0xcc, 0x7e, 0x5e, 0x11, 0x33, 0xf9, 0x9f, 0x39, 0xc8, 0x29, 0xd8, 0xb1, 0x29, 0x26, 0xa0, 0x2a,
|
||||
0xe4, 0xf1, 0x49, 0x07, 0x73, 0x32, 0x14, 0x8f, 0x24, 0x13, 0x5c, 0xba, 0xee, 0x4a, 0xd2, 0x4c,
|
||||
0xee, 0xa9, 0xa1, 0x5b, 0x82, 0xf0, 0x45, 0x73, 0x37, 0xa1, 0x1e, 0x64, 0x7c, 0x77, 0x5c, 0xc6,
|
||||
0x97, 0x8c, 0x4c, 0xde, 0x5c, 0x6b, 0x8c, 0xf2, 0xdd, 0x12, 0x94, 0x2f, 0x35, 0xe7, 0x65, 0x21,
|
||||
0xce, 0x57, 0x0b, 0x71, 0xbe, 0xf4, 0x9c, 0x6d, 0x46, 0x90, 0xbe, 0x5a, 0x88, 0xf4, 0x65, 0xe6,
|
||||
0x18, 0x89, 0x60, 0x7d, 0x77, 0x5c, 0xd6, 0x97, 0x9d, 0xb3, 0xed, 0x31, 0xda, 0xf7, 0x20, 0x4c,
|
||||
0xfb, 0x38, 0x65, 0xbb, 0x16, 0xa9, 0x1d, 0xc9, 0xfb, 0x7e, 0x12, 0xe0, 0x7d, 0xf9, 0x48, 0xd2,
|
||||
0xc5, 0x8d, 0x4c, 0x21, 0x7e, 0xb5, 0x10, 0xf1, 0x83, 0x39, 0x3e, 0x88, 0x60, 0x7e, 0xef, 0x06,
|
||||
0x99, 0xdf, 0x52, 0x24, 0x79, 0x14, 0x87, 0x66, 0x1a, 0xf5, 0xbb, 0xe7, 0x51, 0xbf, 0xe5, 0x48,
|
||||
0xee, 0x2a, 0xf6, 0x30, 0xce, 0xfd, 0x9a, 0x13, 0xdc, 0x8f, 0x73, 0xb5, 0x57, 0x22, 0x4d, 0xcc,
|
||||
0x21, 0x7f, 0xcd, 0x09, 0xf2, 0x57, 0x9c, 0x63, 0x70, 0x0e, 0xfb, 0xfb, 0xf5, 0x74, 0xf6, 0x17,
|
||||
0xcd, 0xcf, 0xc4, 0xcf, 0x5c, 0x8c, 0xfe, 0xa9, 0x11, 0xf4, 0xaf, 0xcc, 0xcc, 0xbf, 0x16, 0x69,
|
||||
0xfe, 0xec, 0xfc, 0xef, 0x06, 0x4d, 0xb3, 0x63, 0xc0, 0x41, 0xa1, 0x0a, 0x0f, 0x87, 0xd6, 0x50,
|
||||
0x50, 0x2b, 0x3e, 0x91, 0x5f, 0xa5, 0x89, 0xdf, 0x07, 0x89, 0x19, 0x5c, 0x91, 0xa5, 0x84, 0x00,
|
||||
0x30, 0xc8, 0x7f, 0x8a, 0xfb, 0xba, 0x2c, 0x57, 0x06, 0x49, 0x43, 0x5e, 0x90, 0x86, 0x00, 0x85,
|
||||
0x4c, 0x84, 0x29, 0xe4, 0x3a, 0x2c, 0x51, 0xa8, 0x1f, 0x63, 0x87, 0x9a, 0xed, 0xb2, 0x43, 0x74,
|
||||
0x13, 0x56, 0x58, 0x2e, 0xe7, 0x44, 0x53, 0xe0, 0x7b, 0x8a, 0xa5, 0xa9, 0x12, 0x7d, 0xc0, 0x0f,
|
||||
0x27, 0x07, 0xfa, 0x37, 0xe0, 0x5c, 0x40, 0xd6, 0x4b, 0x21, 0x9c, 0x12, 0x95, 0x3d, 0xe9, 0x6d,
|
||||
0x91, 0x4b, 0x3e, 0xf0, 0x1d, 0xe4, 0x33, 0x4f, 0x04, 0xa9, 0x8e, 0xa5, 0x63, 0x01, 0xf0, 0x6c,
|
||||
0x4c, 0xd9, 0x68, 0xdf, 0xea, 0x0a, 0x18, 0xa7, 0x43, 0x2a, 0xe5, 0xa1, 0x60, 0x9e, 0x83, 0x9c,
|
||||
0xfc, 0x97, 0xb8, 0x6f, 0xcf, 0x27, 0xa3, 0xd3, 0x78, 0x63, 0xfc, 0xff, 0xc3, 0x1b, 0x13, 0xdf,
|
||||
0x9a, 0x37, 0x06, 0x13, 0x6c, 0x32, 0x9c, 0x60, 0xff, 0x1d, 0xf7, 0xbf, 0xb0, 0xc7, 0x02, 0xbf,
|
||||
0x9d, 0x47, 0xfc, 0x6c, 0x99, 0x66, 0xdf, 0x4b, 0x64, 0x4b, 0xc1, 0xed, 0x33, 0xec, 0xbd, 0x61,
|
||||
0x6e, 0x9f, 0xe5, 0xf9, 0x93, 0x4d, 0xd0, 0x5d, 0xc8, 0xb3, 0xa6, 0x8b, 0x6a, 0xd9, 0x8e, 0x00,
|
||||
0xdc, 0x4b, 0xc1, 0xbd, 0xf2, 0xde, 0xca, 0xc6, 0x01, 0x95, 0x69, 0xda, 0x8e, 0x92, 0xb3, 0xc5,
|
||||
0x28, 0x40, 0x04, 0xf2, 0x21, 0x3e, 0x7a, 0x19, 0xf2, 0xf4, 0xd7, 0x3b, 0xb6, 0xd6, 0xc1, 0x0c,
|
||||
0x3c, 0xf3, 0x8a, 0xbf, 0x20, 0x3f, 0x06, 0x34, 0x09, 0xdf, 0xa8, 0x01, 0x19, 0x7c, 0x8c, 0x4d,
|
||||
0x42, 0xbf, 0x1a, 0x75, 0xf7, 0xf9, 0x29, 0x64, 0x0f, 0x9b, 0xa4, 0x5a, 0xa1, 0x4e, 0xfe, 0xd7,
|
||||
0x37, 0xeb, 0x65, 0x2e, 0xfd, 0xba, 0x35, 0x30, 0x08, 0x1e, 0xd8, 0xe4, 0x54, 0x11, 0xfa, 0xf2,
|
||||
0xe7, 0x09, 0xca, 0xbc, 0x42, 0xd0, 0x3e, 0xd5, 0xb7, 0x6e, 0x00, 0x25, 0x02, 0xac, 0x7b, 0x31,
|
||||
0x7f, 0xaf, 0x01, 0x74, 0x35, 0x47, 0x7d, 0xaa, 0x99, 0x04, 0xeb, 0xc2, 0xe9, 0x81, 0x15, 0x24,
|
||||
0x41, 0x8e, 0xce, 0x46, 0x0e, 0xd6, 0x45, 0x01, 0xe0, 0xcd, 0x03, 0xfb, 0xcc, 0x7e, 0xb7, 0x7d,
|
||||
0x86, 0xbd, 0x9c, 0x1b, 0xf7, 0xf2, 0xef, 0x12, 0x7e, 0x94, 0xf8, 0x24, 0xf5, 0xfb, 0xe7, 0x87,
|
||||
0xdf, 0xb3, 0xca, 0x35, 0x9c, 0x63, 0xd1, 0x21, 0xac, 0x78, 0x51, 0xaa, 0x8e, 0x58, 0xf4, 0xba,
|
||||
0xe7, 0x6e, 0xd1, 0x30, 0x2f, 0x1f, 0x87, 0x97, 0x1d, 0xf4, 0x73, 0xb8, 0x30, 0x86, 0x40, 0x9e,
|
||||
0xe9, 0xc4, 0x82, 0x40, 0xf4, 0x52, 0x18, 0x88, 0x5c, 0xcb, 0xbe, 0xaf, 0x92, 0xdf, 0x31, 0x36,
|
||||
0x76, 0x68, 0x31, 0x14, 0x64, 0x0c, 0x53, 0xbf, 0xfe, 0x35, 0x28, 0x0c, 0x31, 0xa1, 0xf5, 0x79,
|
||||
0xa8, 0xdc, 0x5c, 0xe6, 0x8b, 0xa2, 0x88, 0x3d, 0x80, 0x97, 0xa6, 0x32, 0x07, 0xf4, 0x23, 0xc8,
|
||||
0xfb, 0xa4, 0x23, 0x1e, 0x51, 0xb9, 0x79, 0xd5, 0x88, 0x2f, 0x2b, 0xff, 0x39, 0xee, 0x9b, 0x0c,
|
||||
0xd7, 0x37, 0x75, 0xc8, 0x0c, 0xb1, 0x33, 0xea, 0xf3, 0x8a, 0xa3, 0xb8, 0xf5, 0xc6, 0x62, 0x9c,
|
||||
0x83, 0xae, 0x8e, 0xfa, 0x44, 0x11, 0xca, 0xf2, 0x63, 0xc8, 0xf0, 0x15, 0xb4, 0x04, 0xd9, 0x87,
|
||||
0xfb, 0xbb, 0xfb, 0xcd, 0x0f, 0xf7, 0xcb, 0x31, 0x04, 0x90, 0xd9, 0xae, 0xd5, 0xea, 0x07, 0xad,
|
||||
0x72, 0x1c, 0xe5, 0x21, 0xbd, 0x5d, 0x6d, 0x2a, 0xad, 0x72, 0x82, 0x2e, 0x2b, 0xf5, 0xf7, 0xeb,
|
||||
0xb5, 0x56, 0x39, 0x89, 0x56, 0xa0, 0xc0, 0xc7, 0xea, 0x83, 0xa6, 0xf2, 0xc1, 0x76, 0xab, 0x9c,
|
||||
0x0a, 0x2c, 0x1d, 0xd6, 0xf7, 0xef, 0xd7, 0x95, 0x72, 0x5a, 0x7e, 0x93, 0x96, 0x34, 0x11, 0x2c,
|
||||
0xc5, 0x2f, 0x5e, 0xe2, 0x81, 0xe2, 0x45, 0xfe, 0x63, 0x02, 0xa4, 0x68, 0xea, 0x81, 0xde, 0x1f,
|
||||
0xdb, 0xf8, 0xd6, 0x19, 0x78, 0xcb, 0xd8, 0xee, 0xd1, 0x75, 0x28, 0x0e, 0xf1, 0x11, 0x26, 0x9d,
|
||||
0x1e, 0xa7, 0x42, 0x3c, 0xb1, 0x15, 0x94, 0x82, 0x58, 0x65, 0x4a, 0x0e, 0x17, 0xfb, 0x04, 0x77,
|
||||
0x88, 0xca, 0xeb, 0x28, 0x7e, 0xe8, 0xf2, 0x54, 0x8c, 0xae, 0x1e, 0xf2, 0x45, 0xf9, 0xe3, 0x33,
|
||||
0xf9, 0x32, 0x0f, 0x69, 0xa5, 0xde, 0x52, 0x7e, 0x51, 0x4e, 0x22, 0x04, 0x45, 0x36, 0x54, 0x0f,
|
||||
0xf7, 0xb7, 0x0f, 0x0e, 0x1b, 0x4d, 0xea, 0xcb, 0x73, 0x50, 0x72, 0x7d, 0xe9, 0x2e, 0xa6, 0xe5,
|
||||
0xff, 0xc6, 0xa1, 0x34, 0x16, 0x20, 0x68, 0x0b, 0xd2, 0x9c, 0x4e, 0x47, 0x35, 0xdd, 0x59, 0x7c,
|
||||
0x8b, 0x68, 0xe2, 0xa2, 0xe8, 0x6d, 0xc8, 0x61, 0xd1, 0x27, 0x98, 0x16, 0x88, 0xbc, 0xbf, 0xe1,
|
||||
0x76, 0x12, 0x84, 0xaa, 0xa7, 0x81, 0xde, 0x81, 0xbc, 0x17, 0xe9, 0xa2, 0x86, 0x7b, 0x79, 0x52,
|
||||
0xdd, 0xc3, 0x08, 0xa1, 0xef, 0xeb, 0xa0, 0x7b, 0x3e, 0x27, 0x4b, 0x4d, 0x92, 0x78, 0xa1, 0xce,
|
||||
0x05, 0x84, 0xb2, 0x2b, 0x2f, 0xd7, 0x60, 0x29, 0xb0, 0x1f, 0x74, 0x09, 0xf2, 0x03, 0xed, 0x44,
|
||||
0xf4, 0x9f, 0x78, 0x07, 0x21, 0x37, 0xd0, 0x4e, 0x78, 0xeb, 0xe9, 0x02, 0x64, 0xe9, 0xc3, 0xae,
|
||||
0xc6, 0xd1, 0x26, 0xa9, 0x64, 0x06, 0xda, 0xc9, 0x7b, 0x9a, 0x23, 0x7f, 0x04, 0xc5, 0x70, 0xef,
|
||||
0x85, 0x9e, 0xc4, 0xa1, 0x35, 0x32, 0x75, 0x66, 0x23, 0xad, 0xf0, 0x09, 0xba, 0x0d, 0xe9, 0x63,
|
||||
0x8b, 0x83, 0xd5, 0xf4, 0x90, 0x7d, 0x64, 0x11, 0x1c, 0xe8, 0xdd, 0x70, 0x69, 0xf9, 0x33, 0x48,
|
||||
0x33, 0xf0, 0xa1, 0x40, 0xc2, 0xba, 0x28, 0x82, 0x8f, 0xd2, 0x31, 0xfa, 0x08, 0x40, 0x23, 0x64,
|
||||
0x68, 0xb4, 0x47, 0xbe, 0xe1, 0xf5, 0xe9, 0xe0, 0xb5, 0xed, 0xca, 0x55, 0x2f, 0x0b, 0x14, 0x5b,
|
||||
0xf5, 0x55, 0x03, 0x48, 0x16, 0x30, 0x28, 0xef, 0x43, 0x31, 0xac, 0x1b, 0xec, 0x67, 0x2e, 0x4f,
|
||||
0xe9, 0x67, 0x7a, 0x9c, 0xc7, 0x63, 0x4c, 0x49, 0xde, 0x31, 0x63, 0x13, 0xf9, 0x59, 0x1c, 0x72,
|
||||
0xad, 0x13, 0x71, 0xac, 0x23, 0x9a, 0x35, 0xbe, 0x6a, 0x22, 0xd8, 0x9a, 0xe0, 0xdd, 0x9f, 0xa4,
|
||||
0xd7, 0x53, 0x7a, 0xd7, 0x0b, 0xdc, 0xd4, 0xa2, 0xc5, 0xa3, 0xdb, 0x5c, 0x13, 0x60, 0xf5, 0x16,
|
||||
0xe4, 0xbd, 0x53, 0x45, 0x89, 0xbd, 0xa6, 0xeb, 0x43, 0xec, 0x38, 0x62, 0x6f, 0xee, 0x94, 0xf5,
|
||||
0xfe, 0xac, 0xa7, 0xa2, 0xf9, 0x91, 0x54, 0xf8, 0x44, 0xd6, 0xa1, 0x34, 0x96, 0xb6, 0xd0, 0x5b,
|
||||
0x90, 0xb5, 0x47, 0x6d, 0xd5, 0x75, 0xcf, 0x58, 0xf0, 0xb8, 0x24, 0x6f, 0xd4, 0xee, 0x1b, 0x9d,
|
||||
0x5d, 0x7c, 0xea, 0xfe, 0x18, 0x7b, 0xd4, 0xde, 0xe5, 0x5e, 0xe4, 0x6f, 0x49, 0x04, 0xdf, 0x72,
|
||||
0x0c, 0x39, 0xf7, 0x50, 0xa0, 0x9f, 0x06, 0xe3, 0xc4, 0xed, 0x08, 0x47, 0xa6, 0x52, 0x61, 0x3e,
|
||||
0x10, 0x26, 0x37, 0x61, 0xc5, 0x31, 0xba, 0x26, 0xd6, 0x55, 0xbf, 0xb4, 0x60, 0x6f, 0xcb, 0x29,
|
||||
0x25, 0xfe, 0x60, 0xcf, 0xad, 0x2b, 0xe4, 0xff, 0xc4, 0x21, 0xe7, 0x06, 0x2c, 0x7a, 0x33, 0x70,
|
||||
0xee, 0x8a, 0x53, 0x1a, 0x25, 0xae, 0xa0, 0xdf, 0xbe, 0x0b, 0xff, 0xd6, 0xc4, 0xd9, 0x7f, 0x6b,
|
||||
0x54, 0x1f, 0xd6, 0x6d, 0x88, 0xa7, 0xce, 0xdc, 0x10, 0x7f, 0x1d, 0x10, 0xb1, 0x88, 0xd6, 0x57,
|
||||
0x8f, 0x2d, 0x62, 0x98, 0x5d, 0x95, 0x3b, 0x9b, 0x33, 0xaa, 0x32, 0x7b, 0xf2, 0x88, 0x3d, 0x38,
|
||||
0x60, 0x7e, 0xff, 0x4d, 0x1c, 0x72, 0x5e, 0x6e, 0x3c, 0x6b, 0x37, 0xee, 0x3c, 0x64, 0x04, 0xfc,
|
||||
0xf3, 0x76, 0x9c, 0x98, 0x79, 0x8d, 0xe1, 0x54, 0xa0, 0x31, 0x2c, 0x41, 0x6e, 0x80, 0x89, 0xc6,
|
||||
0x08, 0x02, 0xaf, 0xee, 0xbc, 0xf9, 0xcd, 0x7b, 0xb0, 0x14, 0x68, 0x8c, 0xd2, 0xc8, 0xdb, 0xaf,
|
||||
0x7f, 0x58, 0x8e, 0x49, 0xd9, 0x67, 0x5f, 0x5e, 0x4d, 0xee, 0xe3, 0xa7, 0xf4, 0xcc, 0x2a, 0xf5,
|
||||
0x5a, 0xa3, 0x5e, 0xdb, 0x2d, 0xc7, 0xa5, 0xa5, 0x67, 0x5f, 0x5e, 0xcd, 0x2a, 0x98, 0xf5, 0x57,
|
||||
0x6e, 0x36, 0x60, 0x39, 0xf8, 0x55, 0xc2, 0x19, 0x04, 0x41, 0xf1, 0xfe, 0xc3, 0x83, 0xbd, 0x9d,
|
||||
0xda, 0x76, 0xab, 0xae, 0x3e, 0x6a, 0xb6, 0xea, 0xe5, 0x38, 0xba, 0x00, 0xe7, 0xf6, 0x76, 0xde,
|
||||
0x6b, 0xb4, 0xd4, 0xda, 0xde, 0x4e, 0x7d, 0xbf, 0xa5, 0x6e, 0xb7, 0x5a, 0xdb, 0xb5, 0xdd, 0x72,
|
||||
0x62, 0xeb, 0x73, 0x80, 0xd2, 0x76, 0xb5, 0xb6, 0x43, 0xb3, 0x9f, 0xd1, 0xd1, 0x44, 0xff, 0x2a,
|
||||
0xc5, 0x8a, 0xeb, 0x99, 0x37, 0xb2, 0xd2, 0xec, 0xf6, 0x1d, 0x7a, 0x00, 0x69, 0x56, 0x77, 0xa3,
|
||||
0xd9, 0x57, 0xb4, 0xd2, 0x9c, 0x7e, 0x1e, 0xfd, 0x31, 0x2c, 0x3c, 0x66, 0xde, 0xd9, 0x4a, 0xb3,
|
||||
0xdb, 0x7b, 0x48, 0x81, 0xbc, 0x5f, 0x38, 0xcf, 0xbf, 0xc3, 0x95, 0x16, 0x68, 0xf9, 0x51, 0x9b,
|
||||
0x7e, 0x59, 0x30, 0xff, 0x4e, 0x53, 0x5a, 0x00, 0xc0, 0xd0, 0x1e, 0x64, 0xdd, 0x82, 0x6b, 0xde,
|
||||
0x2d, 0xab, 0x34, 0xb7, 0x1d, 0x47, 0x3f, 0x01, 0x2f, 0x8c, 0x67, 0x5f, 0x19, 0x4b, 0x73, 0x7a,
|
||||
0x8b, 0x68, 0x07, 0x32, 0x82, 0xeb, 0xce, 0xb9, 0x39, 0x95, 0xe6, 0xb5, 0xd7, 0xa8, 0xd3, 0xfc,
|
||||
0x8e, 0xc3, 0xfc, 0x8b, 0x70, 0x69, 0x81, 0xb6, 0x29, 0x7a, 0x08, 0x10, 0x28, 0x83, 0x17, 0xb8,
|
||||
0xe1, 0x96, 0x16, 0x69, 0x87, 0xa2, 0x26, 0xe4, 0xbc, 0x72, 0x67, 0xee, 0x7d, 0xb3, 0x34, 0xbf,
|
||||
0x2f, 0x89, 0x1e, 0x43, 0x21, 0xcc, 0xf3, 0x17, 0xbb, 0x45, 0x96, 0x16, 0x6c, 0x38, 0x52, 0xfb,
|
||||
0x61, 0xd2, 0xbf, 0xd8, 0xad, 0xb2, 0xb4, 0x60, 0xff, 0x11, 0x7d, 0x02, 0x2b, 0x93, 0xa4, 0x7c,
|
||||
0xf1, 0x4b, 0x66, 0xe9, 0x0c, 0x1d, 0x49, 0x34, 0x00, 0x34, 0x85, 0xcc, 0x9f, 0xe1, 0xce, 0x59,
|
||||
0x3a, 0x4b, 0x83, 0xb2, 0x5a, 0xff, 0xea, 0xf9, 0x5a, 0xfc, 0xeb, 0xe7, 0x6b, 0xf1, 0x7f, 0x3c,
|
||||
0x5f, 0x8b, 0x7f, 0xf1, 0x62, 0x2d, 0xf6, 0xf5, 0x8b, 0xb5, 0xd8, 0xdf, 0x5e, 0xac, 0xc5, 0x7e,
|
||||
0xf9, 0x5a, 0xd7, 0x20, 0xbd, 0x51, 0x7b, 0xa3, 0x63, 0x0d, 0x36, 0x83, 0x7f, 0x88, 0x99, 0xf6,
|
||||
0x27, 0x9d, 0x76, 0x86, 0x25, 0xaa, 0x5b, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x3b, 0xae, 0x48,
|
||||
0xb4, 0xc4, 0x23, 0x00, 0x00,
|
||||
0x11, 0xc6, 0xfb, 0xd1, 0x24, 0x1e, 0x1c, 0xd1, 0x32, 0x0c, 0xcb, 0xa4, 0xbc, 0x2e, 0x39, 0x96,
|
||||
0x6c, 0x93, 0x36, 0x55, 0x72, 0xa4, 0xd8, 0x89, 0x0d, 0x40, 0x90, 0x41, 0x93, 0x26, 0x98, 0x21,
|
||||
0x44, 0xe7, 0x65, 0xad, 0x17, 0xc0, 0x10, 0x58, 0x0b, 0xd8, 0x5d, 0x63, 0x07, 0x14, 0xe9, 0x63,
|
||||
0x5c, 0xb9, 0x28, 0x17, 0xe7, 0x96, 0x8b, 0xff, 0x47, 0x4e, 0xb9, 0xe4, 0xe2, 0xaa, 0x5c, 0x7c,
|
||||
0xcc, 0xc9, 0x49, 0x49, 0x95, 0x4b, 0xfe, 0x40, 0x0e, 0xa9, 0x54, 0x52, 0xf3, 0xd8, 0x17, 0x80,
|
||||
0x05, 0x40, 0x3b, 0xb7, 0xdc, 0x76, 0x7a, 0xbb, 0x7b, 0x76, 0x1a, 0xd3, 0xdf, 0x7c, 0xdd, 0x03,
|
||||
0x78, 0x9e, 0x12, 0xa3, 0x4b, 0x46, 0x43, 0xdd, 0xa0, 0xdb, 0x5a, 0xbb, 0xa3, 0x6f, 0xd3, 0x73,
|
||||
0x8b, 0xd8, 0x5b, 0xd6, 0xc8, 0xa4, 0x26, 0x2a, 0x78, 0x2f, 0xb7, 0xd8, 0xcb, 0xf2, 0x0b, 0x3e,
|
||||
0xed, 0xce, 0xe8, 0xdc, 0xa2, 0xe6, 0xb6, 0x35, 0x32, 0xcd, 0x13, 0xa1, 0x5f, 0xbe, 0x32, 0xfd,
|
||||
0xfa, 0x21, 0x39, 0x97, 0xde, 0x02, 0xc6, 0x7c, 0x96, 0x6d, 0x4b, 0x1b, 0x69, 0x43, 0xe7, 0xf5,
|
||||
0x66, 0xcf, 0x34, 0x7b, 0x03, 0xb2, 0xcd, 0x47, 0xed, 0xf1, 0xc9, 0x36, 0xd5, 0x87, 0xc4, 0xa6,
|
||||
0xda, 0xd0, 0x92, 0x0a, 0xeb, 0x3d, 0xb3, 0x67, 0xf2, 0xc7, 0x6d, 0xf6, 0x24, 0xa4, 0xca, 0xef,
|
||||
0x32, 0x90, 0xc6, 0xe4, 0xb3, 0x31, 0xb1, 0x29, 0xda, 0x81, 0x04, 0xe9, 0xf4, 0xcd, 0x52, 0xf4,
|
||||
0x6a, 0xf4, 0x95, 0x95, 0x9d, 0x2b, 0x5b, 0x13, 0x9f, 0xbf, 0x25, 0xf5, 0xea, 0x9d, 0xbe, 0xd9,
|
||||
0x88, 0x60, 0xae, 0x8b, 0x6e, 0x41, 0xf2, 0x64, 0x30, 0xb6, 0xfb, 0xa5, 0x18, 0x37, 0x7a, 0x21,
|
||||
0xcc, 0xe8, 0x1e, 0x53, 0x6a, 0x44, 0xb0, 0xd0, 0x66, 0x53, 0xe9, 0xc6, 0x89, 0x59, 0x8a, 0xcf,
|
||||
0x9f, 0x6a, 0xd7, 0x38, 0xe1, 0x53, 0x31, 0x5d, 0x54, 0x05, 0xb0, 0x09, 0x55, 0x4d, 0x8b, 0xea,
|
||||
0xa6, 0x51, 0x4a, 0x70, 0xcb, 0x17, 0xc3, 0x2c, 0x8f, 0x08, 0x6d, 0x72, 0xc5, 0x46, 0x04, 0x67,
|
||||
0x6d, 0x67, 0xc0, 0x7c, 0xe8, 0x86, 0x4e, 0xd5, 0x4e, 0x5f, 0xd3, 0x8d, 0x52, 0x72, 0xbe, 0x8f,
|
||||
0x5d, 0x43, 0xa7, 0x35, 0xa6, 0xc8, 0x7c, 0xe8, 0xce, 0x80, 0x2d, 0xf9, 0xb3, 0x31, 0x19, 0x9d,
|
||||
0x97, 0x52, 0xf3, 0x97, 0xfc, 0x53, 0xa6, 0xc4, 0x96, 0xcc, 0xb5, 0x51, 0x1d, 0x56, 0xda, 0xa4,
|
||||
0xa7, 0x1b, 0x6a, 0x7b, 0x60, 0x76, 0x1e, 0x96, 0xd2, 0xdc, 0x58, 0x09, 0x33, 0xae, 0x32, 0xd5,
|
||||
0x2a, 0xd3, 0x6c, 0x44, 0x30, 0xb4, 0xdd, 0x11, 0x7a, 0x07, 0x32, 0x9d, 0x3e, 0xe9, 0x3c, 0x54,
|
||||
0xe9, 0x59, 0x29, 0xc3, 0x7d, 0x6c, 0x86, 0xf9, 0xa8, 0x31, 0xbd, 0xd6, 0x59, 0x23, 0x82, 0xd3,
|
||||
0x1d, 0xf1, 0xc8, 0xd6, 0xdf, 0x25, 0x03, 0xfd, 0x94, 0x8c, 0x98, 0x7d, 0x76, 0xfe, 0xfa, 0xef,
|
||||
0x0a, 0x4d, 0xee, 0x21, 0xdb, 0x75, 0x06, 0xe8, 0x5d, 0xc8, 0x12, 0xa3, 0x2b, 0x97, 0x01, 0xdc,
|
||||
0xc5, 0xd5, 0xd0, 0xbd, 0x62, 0x74, 0x9d, 0x45, 0x64, 0x88, 0x7c, 0x46, 0xb7, 0x21, 0xd5, 0x31,
|
||||
0x87, 0x43, 0x9d, 0x96, 0x56, 0xb8, 0xf5, 0x46, 0xe8, 0x02, 0xb8, 0x56, 0x23, 0x82, 0xa5, 0x3e,
|
||||
0x3a, 0x80, 0xfc, 0x40, 0xb7, 0xa9, 0x6a, 0x1b, 0x9a, 0x65, 0xf7, 0x4d, 0x6a, 0x97, 0x56, 0xb9,
|
||||
0x87, 0x6b, 0x61, 0x1e, 0xf6, 0x75, 0x9b, 0x1e, 0x39, 0xca, 0x8d, 0x08, 0xce, 0x0d, 0xfc, 0x02,
|
||||
0xe6, 0xcf, 0x3c, 0x39, 0x21, 0x23, 0xd7, 0x61, 0x29, 0x37, 0xdf, 0x5f, 0x93, 0x69, 0x3b, 0xf6,
|
||||
0xcc, 0x9f, 0xe9, 0x17, 0xa0, 0x5f, 0xc2, 0xa5, 0x81, 0xa9, 0x75, 0x5d, 0x77, 0x6a, 0xa7, 0x3f,
|
||||
0x36, 0x1e, 0x96, 0xf2, 0xdc, 0xe9, 0xf5, 0xd0, 0x8f, 0x34, 0xb5, 0xae, 0xe3, 0xa2, 0xc6, 0x0c,
|
||||
0x1a, 0x11, 0xbc, 0x36, 0x98, 0x14, 0xa2, 0x07, 0xb0, 0xae, 0x59, 0xd6, 0xe0, 0x7c, 0xd2, 0x7b,
|
||||
0x81, 0x7b, 0xbf, 0x11, 0xe6, 0xbd, 0xc2, 0x6c, 0x26, 0xdd, 0x23, 0x6d, 0x4a, 0x5a, 0x4d, 0x43,
|
||||
0xf2, 0x54, 0x1b, 0x8c, 0x89, 0xf2, 0x03, 0x58, 0xf1, 0xa5, 0x3a, 0x2a, 0x41, 0x7a, 0x48, 0x6c,
|
||||
0x5b, 0xeb, 0x11, 0x8e, 0x0c, 0x59, 0xec, 0x0c, 0x95, 0x3c, 0xac, 0xfa, 0xd3, 0x5b, 0x19, 0xba,
|
||||
0x86, 0x2c, 0x71, 0x99, 0xe1, 0x29, 0x19, 0xd9, 0x2c, 0x5b, 0xa5, 0xa1, 0x1c, 0xa2, 0x97, 0x20,
|
||||
0xc7, 0xb7, 0x8f, 0xea, 0xbc, 0x67, 0xe8, 0x91, 0xc0, 0xab, 0x5c, 0x78, 0x2c, 0x95, 0x36, 0x61,
|
||||
0xc5, 0xda, 0xb1, 0x5c, 0x95, 0x38, 0x57, 0x01, 0x6b, 0xc7, 0x92, 0x0a, 0xca, 0x8f, 0xa0, 0x38,
|
||||
0x99, 0xed, 0xa8, 0x08, 0xf1, 0x87, 0xe4, 0x5c, 0xce, 0xc7, 0x1e, 0xd1, 0xba, 0x5c, 0x16, 0x9f,
|
||||
0x23, 0x8b, 0xe5, 0x1a, 0xff, 0x1c, 0x73, 0x8d, 0xdd, 0x34, 0x47, 0xb7, 0x21, 0xc1, 0x50, 0x53,
|
||||
0x02, 0x60, 0x79, 0x4b, 0x40, 0xea, 0x96, 0x03, 0xa9, 0x5b, 0x2d, 0x07, 0x52, 0xab, 0x99, 0xaf,
|
||||
0xbf, 0xdd, 0x8c, 0x7c, 0xf9, 0xd7, 0xcd, 0x28, 0xe6, 0x16, 0xe8, 0x39, 0x96, 0x95, 0x9a, 0x6e,
|
||||
0xa8, 0x7a, 0x57, 0xce, 0x93, 0xe6, 0xe3, 0xdd, 0x2e, 0xda, 0x83, 0x62, 0xc7, 0x34, 0x6c, 0x62,
|
||||
0xd8, 0x63, 0x5b, 0x15, 0x90, 0x2d, 0x61, 0x6f, 0x3a, 0x6b, 0x6a, 0x8e, 0xe2, 0x21, 0xd7, 0xc3,
|
||||
0x85, 0x4e, 0x50, 0x80, 0xee, 0x01, 0x9c, 0x6a, 0x03, 0xbd, 0xab, 0x51, 0x73, 0x64, 0x97, 0x12,
|
||||
0x57, 0xe3, 0x33, 0xdd, 0x1c, 0x3b, 0x2a, 0xf7, 0xad, 0xae, 0x46, 0x49, 0x35, 0xc1, 0xbe, 0x16,
|
||||
0xfb, 0x2c, 0xd1, 0xcb, 0x50, 0xd0, 0x2c, 0x4b, 0xb5, 0xa9, 0x46, 0x89, 0xda, 0x3e, 0xa7, 0xc4,
|
||||
0xe6, 0x60, 0xb8, 0x8a, 0x73, 0x9a, 0x65, 0x1d, 0x31, 0x69, 0x95, 0x09, 0xd1, 0x35, 0xc8, 0x33,
|
||||
0xe0, 0xd3, 0xb5, 0x81, 0xda, 0x27, 0x7a, 0xaf, 0x4f, 0x39, 0xe8, 0xc5, 0x71, 0x4e, 0x4a, 0x1b,
|
||||
0x5c, 0xa8, 0x74, 0xdd, 0x8d, 0xc0, 0x41, 0x0f, 0x21, 0x48, 0x74, 0x35, 0xaa, 0xf1, 0x40, 0xae,
|
||||
0x62, 0xfe, 0xcc, 0x64, 0x96, 0x46, 0xfb, 0x32, 0x3c, 0xfc, 0x19, 0x5d, 0x86, 0x94, 0x74, 0x1b,
|
||||
0xe7, 0x6e, 0xe5, 0x88, 0xfd, 0x66, 0xd6, 0xc8, 0x3c, 0x25, 0x1c, 0xe5, 0x33, 0x58, 0x0c, 0x94,
|
||||
0x7f, 0xc5, 0x60, 0x6d, 0x0a, 0x1e, 0x99, 0xdf, 0xbe, 0x66, 0xf7, 0x9d, 0xb9, 0xd8, 0x33, 0x6a,
|
||||
0x42, 0x71, 0xa0, 0xd9, 0x54, 0x15, 0xb0, 0xa1, 0xfa, 0x8e, 0x9a, 0x69, 0xb0, 0xdc, 0xd7, 0x1c,
|
||||
0xa0, 0x61, 0x9b, 0x56, 0xc6, 0x2a, 0x3f, 0x08, 0x48, 0x11, 0x86, 0xf5, 0xf6, 0xf9, 0xe7, 0x9a,
|
||||
0x41, 0x75, 0x83, 0xa8, 0x53, 0xbf, 0xc0, 0x73, 0x53, 0x4e, 0xeb, 0xa7, 0x7a, 0x97, 0x18, 0x1d,
|
||||
0x27, 0xf4, 0x97, 0x5c, 0xe3, 0x63, 0xef, 0x37, 0xf0, 0x16, 0x9f, 0x0c, 0x2c, 0xde, 0xd9, 0x85,
|
||||
0xa9, 0x0b, 0xef, 0xc2, 0x37, 0x60, 0xdd, 0x20, 0x67, 0xd4, 0xf7, 0x81, 0x2a, 0x0f, 0x4d, 0x9a,
|
||||
0x87, 0x06, 0xb1, 0x77, 0xde, 0xfc, 0x0d, 0x16, 0xa8, 0xeb, 0x50, 0xb4, 0x46, 0xa6, 0x65, 0xda,
|
||||
0x64, 0xa4, 0x6a, 0xdd, 0xee, 0x88, 0xd8, 0x36, 0x3f, 0x55, 0x56, 0x71, 0xc1, 0x91, 0x57, 0x84,
|
||||
0x58, 0xc1, 0x90, 0x0f, 0x9e, 0x2b, 0x28, 0x0f, 0x31, 0x7a, 0x26, 0xe3, 0x1e, 0xa3, 0x67, 0xe8,
|
||||
0x0d, 0x48, 0x30, 0x62, 0xc2, 0x7f, 0xe1, 0xfc, 0x8c, 0x43, 0x5d, 0xda, 0xb5, 0xce, 0x2d, 0x82,
|
||||
0xb9, 0xa6, 0xa2, 0xb8, 0x49, 0xe8, 0x9e, 0x35, 0x93, 0x5e, 0x95, 0xeb, 0x50, 0x98, 0x38, 0x4c,
|
||||
0x7c, 0x91, 0x8b, 0xfa, 0x23, 0xa7, 0x14, 0x20, 0x17, 0x38, 0x39, 0x94, 0xcb, 0xb0, 0x3e, 0xeb,
|
||||
0x20, 0x50, 0xfa, 0xae, 0x3c, 0x00, 0xe8, 0xe8, 0x16, 0x64, 0xdc, 0x93, 0x40, 0x80, 0xc0, 0xf4,
|
||||
0x4f, 0xeb, 0x28, 0x63, 0x57, 0x95, 0x65, 0x3f, 0xcb, 0x26, 0x1e, 0xeb, 0x18, 0xff, 0xf0, 0xb4,
|
||||
0x66, 0x59, 0x2c, 0xc0, 0xca, 0x27, 0x50, 0x0a, 0x43, 0xf9, 0x89, 0x65, 0x24, 0xdc, 0x0d, 0x70,
|
||||
0x19, 0x52, 0x27, 0xe6, 0x68, 0xa8, 0x51, 0xee, 0x2c, 0x87, 0xe5, 0x88, 0x65, 0x85, 0x40, 0xfc,
|
||||
0x38, 0x17, 0x8b, 0x81, 0xa2, 0xc2, 0x73, 0xa1, 0x48, 0xcf, 0x4c, 0x74, 0xa3, 0x4b, 0x44, 0x3c,
|
||||
0x73, 0x58, 0x0c, 0x3c, 0x47, 0xe2, 0x63, 0xc5, 0x80, 0x4d, 0x6b, 0xf3, 0xb5, 0x72, 0xff, 0x59,
|
||||
0x2c, 0x47, 0xca, 0xdf, 0x33, 0x90, 0xc1, 0xc4, 0xb6, 0x18, 0x14, 0xa1, 0x2a, 0x64, 0xc9, 0x59,
|
||||
0x87, 0x08, 0x0e, 0x16, 0x0d, 0xe5, 0x30, 0x42, 0xbb, 0xee, 0x68, 0x32, 0x02, 0xe1, 0x9a, 0xa1,
|
||||
0x9b, 0x92, 0x67, 0x86, 0x53, 0x46, 0x69, 0xee, 0x27, 0x9a, 0x6f, 0x39, 0x44, 0x33, 0x1e, 0xca,
|
||||
0x19, 0x84, 0xd5, 0x04, 0xd3, 0xbc, 0x29, 0x99, 0x66, 0x62, 0xc1, 0x64, 0x01, 0xaa, 0x59, 0x0b,
|
||||
0x50, 0xcd, 0xe4, 0x82, 0x65, 0x86, 0x70, 0xcd, 0x5a, 0x80, 0x6b, 0xa6, 0x16, 0x38, 0x09, 0x21,
|
||||
0x9b, 0x6f, 0x39, 0x64, 0x33, 0xbd, 0x60, 0xd9, 0x13, 0x6c, 0xf3, 0x5e, 0x90, 0x6d, 0x0a, 0xa6,
|
||||
0xf8, 0x52, 0xa8, 0x75, 0x28, 0xdd, 0xfc, 0xb1, 0x8f, 0x6e, 0x66, 0x43, 0xb9, 0x9e, 0x70, 0x32,
|
||||
0x83, 0x6f, 0xd6, 0x02, 0x7c, 0x13, 0x16, 0xc4, 0x20, 0x84, 0x70, 0xbe, 0xe7, 0x27, 0x9c, 0x2b,
|
||||
0xa1, 0x9c, 0x55, 0x6e, 0x9a, 0x59, 0x8c, 0xf3, 0x8e, 0xcb, 0x38, 0x57, 0x43, 0x29, 0xb3, 0x5c,
|
||||
0xc3, 0x24, 0xe5, 0x6c, 0x4e, 0x51, 0x4e, 0x41, 0x11, 0x5f, 0x0e, 0x75, 0xb1, 0x80, 0x73, 0x36,
|
||||
0xa7, 0x38, 0x67, 0x7e, 0x81, 0xc3, 0x05, 0xa4, 0xf3, 0x57, 0xb3, 0x49, 0x67, 0x38, 0x2d, 0x94,
|
||||
0x9f, 0xb9, 0x1c, 0xeb, 0x54, 0x43, 0x58, 0x67, 0x91, 0xbb, 0x7f, 0x35, 0xd4, 0xfd, 0xc5, 0x69,
|
||||
0xe7, 0x75, 0x76, 0xba, 0x4f, 0x00, 0x07, 0x83, 0x2a, 0x32, 0x1a, 0x99, 0x23, 0xc9, 0xe8, 0xc4,
|
||||
0x40, 0x79, 0x85, 0xf1, 0x0d, 0x0f, 0x24, 0xe6, 0x50, 0x54, 0x7e, 0x24, 0xf8, 0x80, 0x41, 0xf9,
|
||||
0x43, 0xd4, 0xb3, 0xe5, 0x47, 0xbb, 0x9f, 0xab, 0x64, 0x25, 0x57, 0xf1, 0x31, 0xd7, 0x58, 0x90,
|
||||
0xb9, 0x6e, 0xc2, 0x0a, 0x83, 0xfa, 0x09, 0x52, 0xaa, 0x59, 0x0e, 0x29, 0x45, 0x37, 0x60, 0x8d,
|
||||
0x53, 0x0f, 0xc1, 0x6f, 0x25, 0xbe, 0x27, 0xf8, 0x31, 0x55, 0x60, 0x2f, 0xc4, 0xe6, 0x14, 0x40,
|
||||
0xff, 0x3a, 0x5c, 0xf2, 0xe9, 0xba, 0x47, 0x88, 0x60, 0x62, 0x45, 0x57, 0xbb, 0x22, 0xcf, 0x92,
|
||||
0x0f, 0xbd, 0x00, 0x79, 0x84, 0x17, 0x41, 0xa2, 0x63, 0x76, 0x89, 0x04, 0x78, 0xfe, 0xcc, 0x48,
|
||||
0xf0, 0xc0, 0xec, 0x49, 0x18, 0x67, 0x8f, 0x4c, 0xcb, 0x45, 0xc1, 0xac, 0x00, 0x39, 0xe5, 0x4f,
|
||||
0x51, 0xcf, 0x9f, 0xc7, 0x81, 0x67, 0xd1, 0xd5, 0xe8, 0xff, 0x86, 0xae, 0xc6, 0xbe, 0x33, 0x5d,
|
||||
0xf5, 0x1f, 0xb0, 0xf1, 0xe0, 0x01, 0xfb, 0xcf, 0xa8, 0xf7, 0x0b, 0xbb, 0xe4, 0xf3, 0xbb, 0x45,
|
||||
0xc4, 0x3b, 0x2d, 0x05, 0x21, 0x93, 0xa7, 0xa5, 0x2c, 0x29, 0x52, 0x7c, 0xde, 0x60, 0x49, 0x21,
|
||||
0x88, 0x95, 0x18, 0xa0, 0xdb, 0x90, 0xe5, 0xdd, 0x1c, 0xd5, 0xb4, 0x6c, 0x09, 0xb8, 0xcf, 0xfb,
|
||||
0xd7, 0x2a, 0x5a, 0x3a, 0x5b, 0x87, 0x4c, 0xa7, 0x69, 0xd9, 0x38, 0x63, 0xc9, 0x27, 0x1f, 0x11,
|
||||
0xc8, 0x06, 0x98, 0xe0, 0x15, 0xc8, 0xb2, 0xaf, 0xb7, 0x2d, 0xad, 0x43, 0x38, 0x78, 0x66, 0xb1,
|
||||
0x27, 0x50, 0x1e, 0x00, 0x9a, 0x86, 0x6f, 0xd4, 0x80, 0x14, 0x39, 0x25, 0x06, 0x65, 0xbf, 0x1a,
|
||||
0x0b, 0xf7, 0xe5, 0x19, 0xdc, 0x94, 0x18, 0xb4, 0x5a, 0x62, 0x41, 0xfe, 0xc7, 0xb7, 0x9b, 0x45,
|
||||
0xa1, 0xfd, 0x9a, 0x39, 0xd4, 0x29, 0x19, 0x5a, 0xf4, 0x1c, 0x4b, 0x7b, 0xe5, 0x8b, 0x18, 0x63,
|
||||
0x5e, 0x01, 0x68, 0x9f, 0x19, 0x5b, 0x27, 0x81, 0x62, 0x3e, 0xb2, 0xbf, 0x5c, 0xbc, 0x37, 0x00,
|
||||
0x7a, 0x9a, 0xad, 0x3e, 0xd2, 0x0c, 0x4a, 0xba, 0x32, 0xe8, 0x3e, 0x09, 0x2a, 0x43, 0x86, 0x8d,
|
||||
0xc6, 0x36, 0xe9, 0xca, 0xba, 0xc3, 0x1d, 0xfb, 0xd6, 0x99, 0xfe, 0x7e, 0xeb, 0x0c, 0x46, 0x39,
|
||||
0x33, 0x19, 0xe5, 0xdf, 0xc4, 0xbc, 0x2c, 0xf1, 0x48, 0xea, 0xff, 0x5f, 0x1c, 0x7e, 0xcb, 0x0b,
|
||||
0xe6, 0xe0, 0x19, 0x8b, 0x8e, 0x60, 0xcd, 0xcd, 0x52, 0x75, 0xcc, 0xb3, 0xd7, 0xd9, 0x77, 0xcb,
|
||||
0xa6, 0x79, 0xf1, 0x34, 0x28, 0xb6, 0xd1, 0xcf, 0xe0, 0xd9, 0x09, 0x04, 0x72, 0x5d, 0xc7, 0x96,
|
||||
0x04, 0xa2, 0x67, 0x82, 0x40, 0xe4, 0x78, 0xf6, 0x62, 0x15, 0xff, 0x9e, 0xb9, 0xb1, 0xcb, 0x8a,
|
||||
0x21, 0x3f, 0x63, 0x98, 0xf9, 0xeb, 0xbf, 0x04, 0xb9, 0x11, 0xa1, 0x9a, 0x6e, 0xa8, 0x81, 0x2a,
|
||||
0x77, 0x55, 0x08, 0x65, 0xed, 0x7c, 0x08, 0xcf, 0xcc, 0x64, 0x0e, 0xe8, 0x87, 0x90, 0xf5, 0x48,
|
||||
0x47, 0x34, 0xa4, 0xd0, 0x74, 0xab, 0x11, 0x4f, 0x57, 0xf9, 0x63, 0xd4, 0x73, 0x19, 0xac, 0x6f,
|
||||
0xea, 0x90, 0x1a, 0x11, 0x7b, 0x3c, 0x10, 0x15, 0x47, 0x7e, 0xe7, 0xf5, 0xe5, 0x38, 0x07, 0x93,
|
||||
0x8e, 0x07, 0x14, 0x4b, 0x63, 0xe5, 0x01, 0xa4, 0x84, 0x04, 0xad, 0x40, 0xfa, 0xfe, 0xc1, 0xde,
|
||||
0x41, 0xf3, 0xa3, 0x83, 0x62, 0x04, 0x01, 0xa4, 0x2a, 0xb5, 0x5a, 0xfd, 0xb0, 0x55, 0x8c, 0xa2,
|
||||
0x2c, 0x24, 0x2b, 0xd5, 0x26, 0x6e, 0x15, 0x63, 0x4c, 0x8c, 0xeb, 0x1f, 0xd4, 0x6b, 0xad, 0x62,
|
||||
0x1c, 0xad, 0x41, 0x4e, 0x3c, 0xab, 0xf7, 0x9a, 0xf8, 0xc3, 0x4a, 0xab, 0x98, 0xf0, 0x89, 0x8e,
|
||||
0xea, 0x07, 0x77, 0xeb, 0xb8, 0x98, 0x54, 0xde, 0x64, 0x25, 0x4d, 0x08, 0x4b, 0xf1, 0x8a, 0x97,
|
||||
0xa8, 0xaf, 0x78, 0x51, 0x7e, 0x1f, 0x83, 0x72, 0x38, 0xf5, 0x40, 0x1f, 0x4c, 0x2c, 0x7c, 0xe7,
|
||||
0x02, 0xbc, 0x65, 0x62, 0xf5, 0xe8, 0x1a, 0xe4, 0x47, 0xe4, 0x84, 0xd0, 0x4e, 0x5f, 0x50, 0x21,
|
||||
0x71, 0xb0, 0xe5, 0x70, 0x4e, 0x4a, 0xb9, 0x91, 0x2d, 0xd4, 0x3e, 0x25, 0x1d, 0xaa, 0x8a, 0x3a,
|
||||
0x4a, 0x6c, 0xba, 0x2c, 0x53, 0x63, 0xd2, 0x23, 0x21, 0x54, 0x3e, 0xb9, 0x50, 0x2c, 0xb3, 0x90,
|
||||
0xc4, 0xf5, 0x16, 0xfe, 0x79, 0x31, 0x8e, 0x10, 0xe4, 0xf9, 0xa3, 0x7a, 0x74, 0x50, 0x39, 0x3c,
|
||||
0x6a, 0x34, 0x59, 0x2c, 0x2f, 0x41, 0xc1, 0x89, 0xa5, 0x23, 0x4c, 0x2a, 0xff, 0x89, 0x42, 0x61,
|
||||
0x22, 0x41, 0xd0, 0x0e, 0x24, 0x05, 0x9d, 0x0e, 0xeb, 0xf5, 0xf3, 0xfc, 0x96, 0xd9, 0x24, 0x54,
|
||||
0xd1, 0x3b, 0x90, 0x21, 0xb2, 0xad, 0x31, 0x2b, 0x11, 0xc5, 0xcd, 0x87, 0xd3, 0xf8, 0x90, 0xa6,
|
||||
0xae, 0x05, 0x7a, 0x17, 0xb2, 0x6e, 0xa6, 0xcb, 0x1a, 0xee, 0xc5, 0x69, 0x73, 0x17, 0x23, 0xa4,
|
||||
0xbd, 0x67, 0x83, 0xee, 0x78, 0x9c, 0x2c, 0x31, 0x4d, 0xe2, 0xa5, 0xb9, 0x50, 0x90, 0xc6, 0x8e,
|
||||
0xbe, 0x52, 0x83, 0x15, 0xdf, 0x7a, 0xd0, 0xf3, 0x90, 0x1d, 0x6a, 0x67, 0xb2, 0xed, 0x25, 0x3a,
|
||||
0x08, 0x99, 0xa1, 0x76, 0x26, 0x3a, 0x5e, 0xcf, 0x42, 0x9a, 0xbd, 0xec, 0x69, 0x02, 0x6d, 0xe2,
|
||||
0x38, 0x35, 0xd4, 0xce, 0xde, 0xd7, 0x6c, 0xe5, 0x63, 0xc8, 0x07, 0x5b, 0x45, 0x6c, 0x27, 0x8e,
|
||||
0xcc, 0xb1, 0xd1, 0xe5, 0x3e, 0x92, 0x58, 0x0c, 0xd0, 0x2d, 0x48, 0x9e, 0x9a, 0x02, 0xac, 0x66,
|
||||
0xa7, 0xec, 0xb1, 0x49, 0x89, 0xaf, 0xd5, 0x24, 0xb4, 0x95, 0xcf, 0x21, 0xc9, 0xc1, 0x87, 0x01,
|
||||
0x09, 0xef, 0xa2, 0x48, 0x3e, 0xca, 0x9e, 0xd1, 0xc7, 0x00, 0x1a, 0xa5, 0x23, 0xbd, 0x3d, 0xf6,
|
||||
0x1c, 0x6f, 0xce, 0x06, 0xaf, 0x8a, 0xa3, 0x57, 0xbd, 0x22, 0x51, 0x6c, 0xdd, 0x33, 0xf5, 0x21,
|
||||
0x99, 0xcf, 0xa1, 0x72, 0x00, 0xf9, 0xa0, 0xad, 0xbf, 0x8d, 0xba, 0x3a, 0xa3, 0x8d, 0xea, 0x72,
|
||||
0x1e, 0x97, 0x31, 0xc5, 0x45, 0xa3, 0x8e, 0x0f, 0x94, 0xc7, 0x51, 0xc8, 0xb4, 0xce, 0xe4, 0xb6,
|
||||
0x0e, 0x69, 0xd6, 0x78, 0xa6, 0x31, 0x7f, 0x6b, 0x42, 0x74, 0x7f, 0xe2, 0x6e, 0x4f, 0xe9, 0x3d,
|
||||
0x37, 0x71, 0x13, 0xcb, 0x16, 0x8f, 0x32, 0xae, 0x0e, 0x58, 0xbd, 0x0d, 0x59, 0x77, 0x57, 0x31,
|
||||
0x62, 0xef, 0xb4, 0xb9, 0xa2, 0x92, 0x47, 0x8a, 0x21, 0x6f, 0x39, 0x9a, 0x8f, 0x64, 0xf3, 0x23,
|
||||
0x8e, 0xc5, 0x40, 0xe9, 0x42, 0x61, 0xe2, 0xd8, 0x42, 0x6f, 0x43, 0xda, 0x1a, 0xb7, 0x55, 0x27,
|
||||
0x3c, 0x13, 0xc9, 0xe3, 0x90, 0xbc, 0x71, 0x7b, 0xa0, 0x77, 0xf6, 0xc8, 0xb9, 0xf3, 0x31, 0xd6,
|
||||
0xb8, 0xbd, 0x27, 0xa2, 0x28, 0x66, 0x89, 0xf9, 0x67, 0x39, 0x85, 0x8c, 0xb3, 0x29, 0xd0, 0x4f,
|
||||
0xfc, 0x79, 0xe2, 0x34, 0xa2, 0x43, 0x8f, 0x52, 0xe9, 0xde, 0x97, 0x26, 0x37, 0x60, 0xcd, 0xd6,
|
||||
0x7b, 0x06, 0xe9, 0xaa, 0x5e, 0x69, 0xc1, 0x67, 0xcb, 0xe0, 0x82, 0x78, 0xb1, 0xef, 0xd4, 0x15,
|
||||
0xca, 0xbf, 0xa3, 0x90, 0x71, 0x12, 0x16, 0xbd, 0xe9, 0xdb, 0x77, 0xf9, 0x19, 0x8d, 0x12, 0x47,
|
||||
0xd1, 0x6b, 0xdf, 0x05, 0xbf, 0x35, 0x76, 0xf1, 0x6f, 0x0d, 0x6b, 0xff, 0x3a, 0x1d, 0xd0, 0xc4,
|
||||
0x85, 0x3b, 0xa0, 0xaf, 0x01, 0xa2, 0x26, 0xd5, 0x06, 0xea, 0xa9, 0x49, 0x75, 0xa3, 0xa7, 0x8a,
|
||||
0x60, 0x0b, 0x46, 0x55, 0xe4, 0x6f, 0x8e, 0xf9, 0x8b, 0x43, 0x1e, 0xf7, 0x5f, 0x47, 0x21, 0xe3,
|
||||
0x9e, 0x8d, 0x17, 0xed, 0xc6, 0x5d, 0x86, 0x94, 0x84, 0x7f, 0xd1, 0x8e, 0x93, 0x23, 0xb7, 0x1f,
|
||||
0x9d, 0xf0, 0xf5, 0xa3, 0xcb, 0x90, 0x19, 0x12, 0xaa, 0x71, 0x82, 0x20, 0xaa, 0x3b, 0x77, 0x7c,
|
||||
0xe3, 0x0e, 0xac, 0xf8, 0x1a, 0xa3, 0x2c, 0xf3, 0x0e, 0xea, 0x1f, 0x15, 0x23, 0xe5, 0xf4, 0xe3,
|
||||
0xaf, 0xae, 0xc6, 0x0f, 0xc8, 0x23, 0xb6, 0x67, 0x71, 0xbd, 0xd6, 0xa8, 0xd7, 0xf6, 0x8a, 0xd1,
|
||||
0xf2, 0xca, 0xe3, 0xaf, 0xae, 0xa6, 0x31, 0xe1, 0xfd, 0x95, 0x1b, 0x0d, 0x58, 0xf5, 0xff, 0x2a,
|
||||
0xc1, 0x13, 0x04, 0x41, 0xfe, 0xee, 0xfd, 0xc3, 0xfd, 0xdd, 0x5a, 0xa5, 0x55, 0x57, 0x8f, 0x9b,
|
||||
0xad, 0x7a, 0x31, 0x8a, 0x9e, 0x85, 0x4b, 0xfb, 0xbb, 0xef, 0x37, 0x5a, 0x6a, 0x6d, 0x7f, 0xb7,
|
||||
0x7e, 0xd0, 0x52, 0x2b, 0xad, 0x56, 0xa5, 0xb6, 0x57, 0x8c, 0xed, 0x7c, 0x01, 0x50, 0xa8, 0x54,
|
||||
0x6b, 0xbb, 0xec, 0xf4, 0xd3, 0x3b, 0x9a, 0xec, 0x5f, 0x25, 0x78, 0x71, 0x3d, 0xf7, 0x22, 0xb8,
|
||||
0x3c, 0xbf, 0x7d, 0x87, 0xee, 0x41, 0x92, 0xd7, 0xdd, 0x68, 0xfe, 0xcd, 0x70, 0x79, 0x41, 0x3f,
|
||||
0x8f, 0x7d, 0x0c, 0x4f, 0x8f, 0xb9, 0x57, 0xc5, 0xe5, 0xf9, 0xed, 0x3d, 0x84, 0x21, 0xeb, 0x15,
|
||||
0xce, 0x8b, 0xaf, 0x8e, 0xcb, 0x4b, 0xb4, 0xfc, 0x98, 0x4f, 0xaf, 0x2c, 0x58, 0x7c, 0x95, 0x5a,
|
||||
0x5e, 0x02, 0xc0, 0xd0, 0x3e, 0xa4, 0x9d, 0x82, 0x6b, 0xd1, 0xe5, 0x6e, 0x79, 0x61, 0x3b, 0x8e,
|
||||
0xfd, 0x04, 0xa2, 0x30, 0x9e, 0x7f, 0x53, 0x5d, 0x5e, 0xd0, 0x5b, 0x44, 0xbb, 0x90, 0x92, 0x5c,
|
||||
0x77, 0xc1, 0x85, 0x6d, 0x79, 0x51, 0x7b, 0x8d, 0x05, 0xcd, 0xeb, 0x38, 0x2c, 0xbe, 0x7f, 0x2f,
|
||||
0x2f, 0xd1, 0x36, 0x45, 0xf7, 0x01, 0x7c, 0x65, 0xf0, 0x12, 0x17, 0xeb, 0xe5, 0x65, 0xda, 0xa1,
|
||||
0xa8, 0x09, 0x19, 0xb7, 0xdc, 0x59, 0x78, 0xcd, 0x5d, 0x5e, 0xdc, 0x97, 0x44, 0x0f, 0x20, 0x17,
|
||||
0xe4, 0xf9, 0xcb, 0x5d, 0x5e, 0x97, 0x97, 0x6c, 0x38, 0x32, 0xff, 0x41, 0xd2, 0xbf, 0xdc, 0x65,
|
||||
0x76, 0x79, 0xc9, 0xfe, 0x23, 0xfa, 0x14, 0xd6, 0xa6, 0x49, 0xf9, 0xf2, 0x77, 0xdb, 0xe5, 0x0b,
|
||||
0x74, 0x24, 0xd1, 0x10, 0xd0, 0x0c, 0x32, 0x7f, 0x81, 0xab, 0xee, 0xf2, 0x45, 0x1a, 0x94, 0xd5,
|
||||
0xfa, 0xd7, 0x4f, 0x36, 0xa2, 0xdf, 0x3c, 0xd9, 0x88, 0xfe, 0xed, 0xc9, 0x46, 0xf4, 0xcb, 0xa7,
|
||||
0x1b, 0x91, 0x6f, 0x9e, 0x6e, 0x44, 0xfe, 0xf2, 0x74, 0x23, 0xf2, 0x8b, 0x57, 0x7b, 0x3a, 0xed,
|
||||
0x8f, 0xdb, 0x5b, 0x1d, 0x73, 0xb8, 0xed, 0xff, 0x1f, 0xce, 0xac, 0x7f, 0xff, 0xb4, 0x53, 0xfc,
|
||||
0xa0, 0xba, 0xf9, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xba, 0x12, 0xce, 0x82, 0x1d, 0x24, 0x00,
|
||||
0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -4583,6 +4609,33 @@ func (m *RequestBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.ProposerAddress) > 0 {
|
||||
i -= len(m.ProposerAddress)
|
||||
copy(dAtA[i:], m.ProposerAddress)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.ProposerAddress)))
|
||||
i--
|
||||
dAtA[i] = 0x42
|
||||
}
|
||||
if len(m.NextValidatorsHash) > 0 {
|
||||
i -= len(m.NextValidatorsHash)
|
||||
copy(dAtA[i:], m.NextValidatorsHash)
|
||||
i = encodeVarintTypes(dAtA, i, uint64(len(m.NextValidatorsHash)))
|
||||
i--
|
||||
dAtA[i] = 0x3a
|
||||
}
|
||||
n18, err18 := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.Time, dAtA[i-github_com_gogo_protobuf_types.SizeOfStdTime(m.Time):])
|
||||
if err18 != nil {
|
||||
return 0, err18
|
||||
}
|
||||
i -= n18
|
||||
i = encodeVarintTypes(dAtA, i, uint64(n18))
|
||||
i--
|
||||
dAtA[i] = 0x32
|
||||
if m.Height != 0 {
|
||||
i = encodeVarintTypes(dAtA, i, uint64(m.Height))
|
||||
i--
|
||||
dAtA[i] = 0x28
|
||||
}
|
||||
if len(m.ByzantineValidators) > 0 {
|
||||
for iNdEx := len(m.ByzantineValidators) - 1; iNdEx >= 0; iNdEx-- {
|
||||
{
|
||||
@@ -4607,16 +4660,6 @@ func (m *RequestBeginBlock) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
{
|
||||
size, err := m.Header.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintTypes(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
if len(m.Hash) > 0 {
|
||||
i -= len(m.Hash)
|
||||
copy(dAtA[i:], m.Hash)
|
||||
@@ -6860,8 +6903,6 @@ func (m *RequestBeginBlock) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = m.Header.Size()
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
l = m.LastCommitInfo.Size()
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
if len(m.ByzantineValidators) > 0 {
|
||||
@@ -6870,6 +6911,19 @@ func (m *RequestBeginBlock) Size() (n int) {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.Height != 0 {
|
||||
n += 1 + sovTypes(uint64(m.Height))
|
||||
}
|
||||
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.Time)
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
l = len(m.NextValidatorsHash)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
l = len(m.ProposerAddress)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovTypes(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -9152,39 +9206,6 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error {
|
||||
m.Hash = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Header", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := m.Header.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field LastCommitInfo", wireType)
|
||||
@@ -9252,6 +9273,126 @@ func (m *RequestBeginBlock) Unmarshal(dAtA []byte) error {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 5:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType)
|
||||
}
|
||||
m.Height = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.Height |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 6:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.Time, dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 7:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.NextValidatorsHash == nil {
|
||||
m.NextValidatorsHash = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 8:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field ProposerAddress", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTypes
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTypes
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.ProposerAddress = append(m.ProposerAddress[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.ProposerAddress == nil {
|
||||
m.ProposerAddress = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTypes(dAtA[iNdEx:])
|
||||
|
||||
69
cmd/tendermint/commands/rollback.go
Normal file
69
cmd/tendermint/commands/rollback.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
cfg "github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/store"
|
||||
)
|
||||
|
||||
var RollbackStateCmd = &cobra.Command{
|
||||
Use: "rollback",
|
||||
Short: "rollback tendermint state by one height",
|
||||
Long: `
|
||||
A state rollback is performed to recover from an incorrect application state transition,
|
||||
when Tendermint has persisted an incorrect app hash and is thus unable to make
|
||||
progress. Rollback overwrites a state at height n with the state at height n - 1.
|
||||
The application should also roll back to height n - 1. No blocks are removed, so upon
|
||||
restarting Tendermint the transactions in block n will be re-executed against the
|
||||
application.
|
||||
`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
height, hash, err := RollbackState(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to rollback state: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Rolled back state to height %d and hash %v", height, hash)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// RollbackState takes the state at the current height n and overwrites it with the state
|
||||
// at height n - 1. Note state here refers to tendermint state not application state.
|
||||
// Returns the latest state height and app hash alongside an error if there was one.
|
||||
func RollbackState(config *cfg.Config) (int64, []byte, error) {
|
||||
// use the parsed config to load the block and state store
|
||||
blockStore, stateStore, err := loadStateAndBlockStore(config)
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
// rollback the last state
|
||||
return state.Rollback(blockStore, stateStore)
|
||||
}
|
||||
|
||||
func loadStateAndBlockStore(config *cfg.Config) (*store.BlockStore, state.Store, error) {
|
||||
dbType := dbm.BackendType(config.DBBackend)
|
||||
|
||||
// Get BlockStore
|
||||
blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
blockStore := store.NewBlockStore(blockStoreDB)
|
||||
|
||||
// Get StateStore
|
||||
stateDB, err := dbm.NewDB("state", dbType, config.DBDir())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
stateStore := state.NewStore(stateDB)
|
||||
|
||||
return blockStore, stateStore, nil
|
||||
}
|
||||
@@ -46,9 +46,7 @@ func AddNodeFlags(cmd *cobra.Command) {
|
||||
"proxy_app",
|
||||
config.ProxyApp,
|
||||
"proxy app address, or one of: 'kvstore',"+
|
||||
" 'persistent_kvstore',"+
|
||||
" 'counter',"+
|
||||
" 'counter_serial' or 'noop' for local testing.")
|
||||
" 'persistent_kvstore', 'counter', 'e2e' or 'noop' for local testing.")
|
||||
cmd.Flags().String("abci", config.ABCI, "specify abci transport (socket | grpc)")
|
||||
|
||||
// rpc flags
|
||||
|
||||
@@ -27,6 +27,7 @@ func main() {
|
||||
cmd.ShowNodeIDCmd,
|
||||
cmd.GenNodeKeyCmd,
|
||||
cmd.VersionCmd,
|
||||
cmd.RollbackStateCmd,
|
||||
debug.DebugCmd,
|
||||
cli.NewCompletionCmd(rootCmd, true),
|
||||
)
|
||||
|
||||
@@ -1017,7 +1017,12 @@ type TxIndexConfig struct {
|
||||
// 1) "null"
|
||||
// 2) "kv" (default) - the simplest possible indexer,
|
||||
// backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
// 3) "psql" - the indexer services backed by PostgreSQL.
|
||||
Indexer string `mapstructure:"indexer"`
|
||||
|
||||
// The PostgreSQL connection configuration, the connection format:
|
||||
// postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
|
||||
PsqlConn string `mapstructure:"psql-conn"`
|
||||
}
|
||||
|
||||
// DefaultTxIndexConfig returns a default configuration for the transaction indexer.
|
||||
|
||||
@@ -866,8 +866,8 @@ func (cs *State) handleMsg(mi msgInfo) {
|
||||
"height", cs.Height,
|
||||
"round", cs.Round,
|
||||
"peer", peerID,
|
||||
"msg_type", fmt.Sprintf("%T", msg),
|
||||
"err", err,
|
||||
"msg", msg,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,24 +31,61 @@ For example:
|
||||
|
||||
would be equal to the composite key of `jack.account.number`.
|
||||
|
||||
Let's take a look at the `[tx_index]` config section:
|
||||
By default, Tendermint will index all transactions by their respective hashes
|
||||
and height and blocks by their height.
|
||||
|
||||
## Configuration
|
||||
|
||||
Operators can configure indexing via the `[tx_index]` section. The `indexer`
|
||||
field takes a series of supported indexers. If `null` is included, indexing will
|
||||
be turned off regardless of other values provided.
|
||||
|
||||
```toml
|
||||
##### transactions indexer configuration options #####
|
||||
[tx_index]
|
||||
[tx-index]
|
||||
|
||||
# What indexer to use for transactions
|
||||
# The backend database to back the indexer.
|
||||
# If indexer is "null", no indexer service will be used.
|
||||
#
|
||||
# The application will set which txs to index. In some cases a node operator will be able
|
||||
# to decide which txs to index based on configuration set in the application.
|
||||
#
|
||||
# Options:
|
||||
# 1) "null"
|
||||
# 2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
|
||||
indexer = "kv"
|
||||
# - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
|
||||
# 3) "psql" - the indexer services backed by PostgreSQL.
|
||||
# indexer = "kv"
|
||||
```
|
||||
|
||||
By default, Tendermint will index all transactions by their respective hashes
|
||||
and height and blocks by their height.
|
||||
### Supported Indexers
|
||||
|
||||
You can turn off indexing completely by setting `tx_index` to `null`.
|
||||
#### KV
|
||||
|
||||
The `kv` indexer type is an embedded key-value store supported by the main
|
||||
underlying Tendermint database. Using the `kv` indexer type allows you to query
|
||||
for block and transaction events directly against Tendermint's RPC. However, the
|
||||
query syntax is limited and so this indexer type might be deprecated or removed
|
||||
entirely in the future.
|
||||
|
||||
#### PostgreSQL
|
||||
|
||||
The `psql` indexer type allows an operator to enable block and transaction event
|
||||
indexing by proxying it to an external PostgreSQL instance allowing for the events
|
||||
to be stored in relational models. Since the events are stored in a RDBMS, operators
|
||||
can leverage SQL to perform a series of rich and complex queries that are not
|
||||
supported by the `kv` indexer type. Since operators can leverage SQL directly,
|
||||
searching is not enabled for the `psql` indexer type via Tendermint's RPC -- any
|
||||
such query will fail.
|
||||
|
||||
Note, the SQL schema is stored in `state/indexer/sink/psql/schema.sql` and operators
|
||||
must explicitly create the relations prior to starting Tendermint and enabling
|
||||
the `psql` indexer type.
|
||||
|
||||
Example:
|
||||
|
||||
```shell
|
||||
$ psql ... -f state/indexer/sink/psql/schema.sql
|
||||
```
|
||||
|
||||
## Default Indexes
|
||||
|
||||
|
||||
13
go.mod
13
go.mod
@@ -3,23 +3,27 @@ module github.com/tendermint/tendermint
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/Workiva/go-datastructures v1.0.52
|
||||
github.com/adlio/schema v1.1.13
|
||||
github.com/btcsuite/btcd v0.21.0-beta
|
||||
github.com/btcsuite/btcutil v1.0.2
|
||||
github.com/confio/ics23/go v0.6.3
|
||||
github.com/cosmos/iavl v0.15.3
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/go-kit/kit v0.10.0
|
||||
github.com/go-logfmt/logfmt v0.5.0
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/protobuf v1.4.3
|
||||
github.com/golang/protobuf v1.5.0
|
||||
github.com/google/orderedcode v0.0.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/gtank/merlin v0.1.1
|
||||
github.com/lib/pq v1.2.0
|
||||
github.com/libp2p/go-buffer-pool v0.0.2
|
||||
github.com/minio/highwayhash v1.0.1
|
||||
github.com/opencontainers/runc v1.0.2 // indirect
|
||||
github.com/ory/dockertest v3.3.5+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.8.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
|
||||
@@ -31,6 +35,7 @@ require (
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tendermint/tm-db v0.6.4
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f
|
||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect
|
||||
google.golang.org/grpc v1.37.0
|
||||
)
|
||||
|
||||
156
go.sum
156
go.sum
@@ -11,6 +11,9 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
@@ -19,6 +22,11 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:
|
||||
github.com/DataDog/zstd v1.4.1 h1:3oxKN3wbHibqx897utPC2LTQU4J+IHWWJO+glkAkpFM=
|
||||
github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU=
|
||||
github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
@@ -27,6 +35,8 @@ github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrd
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI=
|
||||
github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
|
||||
github.com/adlio/schema v1.1.13 h1:LeNMVg5Z1FX+Qgz8tJUijBLRdcpbFUElz+d1489On98=
|
||||
github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
@@ -34,7 +44,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
@@ -50,6 +59,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
|
||||
github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M=
|
||||
@@ -66,21 +76,23 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M=
|
||||
github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg=
|
||||
github.com/confio/ics23/go v0.6.3 h1:PuGK2V1NJWZ8sSkNDq91jgT/cahFEW9RGp4Y5jxulf0=
|
||||
github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg=
|
||||
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6 h1:NmTXa/uVnDyp0TY5MKi197+3HWcnYWfnHGyaFthlnGw=
|
||||
github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
@@ -89,24 +101,21 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd/go.mod h1:3xOIaNNX19p0QrX0VqWa6voPRoJRGGYtny+DH8NEPvE=
|
||||
github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7uMjgxke/I=
|
||||
github.com/cosmos/iavl v0.15.3 h1:xE9r6HW8GeKeoYJN4zefpljZ1oukVScP/7M8oj6SUts=
|
||||
github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.1/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k=
|
||||
github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
|
||||
github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA=
|
||||
@@ -115,6 +124,10 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -125,7 +138,6 @@ github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaB
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
@@ -140,12 +152,12 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
|
||||
@@ -157,12 +169,11 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
@@ -175,7 +186,6 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
@@ -183,8 +193,9 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -195,8 +206,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us=
|
||||
@@ -214,20 +227,15 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI=
|
||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.1/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
||||
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
|
||||
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
||||
@@ -280,7 +288,6 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
@@ -288,9 +295,13 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
@@ -319,10 +330,12 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
@@ -332,8 +345,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
@@ -351,6 +362,15 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.2 h1:opHZMaswlyxz1OuGpBE53Dwe4/xF7EZTY0A2L/FpCOg=
|
||||
github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
@@ -359,6 +379,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
|
||||
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
@@ -413,7 +435,6 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
@@ -421,14 +442,18 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4=
|
||||
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
@@ -446,7 +471,6 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||
@@ -456,7 +480,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
@@ -470,28 +493,24 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
|
||||
github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4=
|
||||
github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg=
|
||||
github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ=
|
||||
github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI=
|
||||
github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8=
|
||||
github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ=
|
||||
github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
@@ -527,8 +546,6 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
|
||||
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -536,7 +553,6 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -551,7 +567,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCc
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -569,24 +584,22 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f h1:w6wWR0H+nyVpbSAQbzVEIACVyr/h8l/BEkY6Sokc7Eg=
|
||||
golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -611,33 +624,43 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b h1:3Dq0eVHn0uaQJmPO+/aYPI/fRMqdrVDbu7MQcku54gg=
|
||||
golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -645,7 +668,6 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@@ -666,7 +688,6 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -695,16 +716,10 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 h1:Rt0FRalMgdSlXAVJvX4pr65KfqaxHXSLkSJRD9pw6g0=
|
||||
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -715,13 +730,6 @@ google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c=
|
||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
@@ -733,16 +741,15 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
@@ -756,7 +763,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -764,6 +770,8 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -239,7 +239,7 @@ func NewClientFromTrustedStore(
|
||||
}
|
||||
|
||||
// Validate the number of witnesses.
|
||||
if len(c.witnesses) < 1 {
|
||||
if len(c.witnesses) == 0 {
|
||||
return nil, ErrNoWitnesses
|
||||
}
|
||||
|
||||
@@ -1001,14 +1001,14 @@ func (c *Client) lightBlockFromPrimary(ctx context.Context, height int64) (*type
|
||||
|
||||
case provider.ErrNoResponse, provider.ErrLightBlockNotFound, provider.ErrHeightTooHigh:
|
||||
// we find a new witness to replace the primary
|
||||
c.logger.Debug("error from light block request from primary, replacing...",
|
||||
c.logger.Info("error from light block request from primary, replacing...",
|
||||
"error", err, "height", height, "primary", c.primary)
|
||||
return c.findNewPrimary(ctx, height, false)
|
||||
|
||||
default:
|
||||
// The light client has most likely received either provider.ErrUnreliableProvider or provider.ErrBadLightBlock
|
||||
// These errors mean that the light client should drop the primary and try with another provider instead
|
||||
c.logger.Error("error from light block request from primary, removing...",
|
||||
c.logger.Info("error from light block request from primary, removing...",
|
||||
"error", err, "height", height, "primary", c.primary)
|
||||
return c.findNewPrimary(ctx, height, true)
|
||||
}
|
||||
@@ -1046,7 +1046,7 @@ func (c *Client) findNewPrimary(ctx context.Context, height int64, remove bool)
|
||||
c.providerMutex.Lock()
|
||||
defer c.providerMutex.Unlock()
|
||||
|
||||
if len(c.witnesses) <= 1 {
|
||||
if len(c.witnesses) == 0 {
|
||||
return nil, ErrNoWitnesses
|
||||
}
|
||||
|
||||
@@ -1117,6 +1117,11 @@ func (c *Client) findNewPrimary(ctx context.Context, height int64, remove bool)
|
||||
}
|
||||
}
|
||||
|
||||
// remove witnesses marked as bad. Removal is done in descending order
|
||||
if err := c.removeWitnesses(witnessesToRemove); err != nil {
|
||||
c.logger.Error("failed to remove witnesses", "err", err, "witnessesToRemove", witnessesToRemove)
|
||||
}
|
||||
|
||||
return nil, lastError
|
||||
}
|
||||
|
||||
@@ -1129,7 +1134,7 @@ func (c *Client) compareFirstHeaderWithWitnesses(ctx context.Context, h *types.S
|
||||
c.providerMutex.Lock()
|
||||
defer c.providerMutex.Unlock()
|
||||
|
||||
if len(c.witnesses) < 1 {
|
||||
if len(c.witnesses) == 0 {
|
||||
return ErrNoWitnesses
|
||||
}
|
||||
|
||||
@@ -1171,7 +1176,7 @@ and remove witness. Otherwise, use the different primary`, e.WitnessIndex), "wit
|
||||
|
||||
// remove witnesses that have misbehaved
|
||||
if err := c.removeWitnesses(witnessesToRemove); err != nil {
|
||||
return err
|
||||
c.logger.Error("failed to remove witnesses", "err", err, "witnessesToRemove", witnessesToRemove)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
ics23 "github.com/confio/ics23/go"
|
||||
"github.com/cosmos/iavl"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/crypto/merkle"
|
||||
"github.com/tendermint/tendermint/libs/bytes"
|
||||
lcmock "github.com/tendermint/tendermint/light/rpc/mocks"
|
||||
tmcrypto "github.com/tendermint/tendermint/proto/tendermint/crypto"
|
||||
rpcmock "github.com/tendermint/tendermint/rpc/client/mocks"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// TestABCIQuery tests ABCIQuery requests and verifies proofs. HAPPY PATH 😀
|
||||
func TestABCIQuery(t *testing.T) {
|
||||
tree, err := iavl.NewMutableTree(dbm.NewMemDB(), 100)
|
||||
require.NoError(t, err)
|
||||
|
||||
var (
|
||||
key = []byte("foo")
|
||||
value = []byte("bar")
|
||||
)
|
||||
tree.Set(key, value)
|
||||
|
||||
commitmentProof, err := tree.GetMembershipProof(key)
|
||||
require.NoError(t, err)
|
||||
|
||||
op := &testOp{
|
||||
Spec: ics23.IavlSpec,
|
||||
Key: key,
|
||||
Proof: commitmentProof,
|
||||
}
|
||||
|
||||
next := &rpcmock.Client{}
|
||||
next.On(
|
||||
"ABCIQueryWithOptions",
|
||||
context.Background(),
|
||||
mock.AnythingOfType("string"),
|
||||
bytes.HexBytes(key),
|
||||
mock.AnythingOfType("client.ABCIQueryOptions"),
|
||||
).Return(&ctypes.ResultABCIQuery{
|
||||
Response: abci.ResponseQuery{
|
||||
Code: 0,
|
||||
Key: key,
|
||||
Value: value,
|
||||
Height: 1,
|
||||
ProofOps: &tmcrypto.ProofOps{
|
||||
Ops: []tmcrypto.ProofOp{op.ProofOp()},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
lc := &lcmock.LightClient{}
|
||||
appHash, _ := hex.DecodeString("5EFD44055350B5CC34DBD26085347A9DBBE44EA192B9286A9FC107F40EA1FAC5")
|
||||
lc.On("VerifyLightBlockAtHeight", context.Background(), int64(2), mock.AnythingOfType("time.Time")).Return(
|
||||
&types.LightBlock{
|
||||
SignedHeader: &types.SignedHeader{
|
||||
Header: &types.Header{AppHash: appHash},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
c := NewClient(next, lc,
|
||||
KeyPathFn(func(_ string, key []byte) (merkle.KeyPath, error) {
|
||||
kp := merkle.KeyPath{}
|
||||
kp = kp.AppendKey(key, merkle.KeyEncodingURL)
|
||||
return kp, nil
|
||||
}))
|
||||
c.RegisterOpDecoder("ics23:iavl", testOpDecoder)
|
||||
res, err := c.ABCIQuery(context.Background(), "/store/accounts/key", key)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotNil(t, res)
|
||||
}
|
||||
|
||||
type testOp struct {
|
||||
Spec *ics23.ProofSpec
|
||||
Key []byte
|
||||
Proof *ics23.CommitmentProof
|
||||
}
|
||||
|
||||
var _ merkle.ProofOperator = testOp{}
|
||||
|
||||
func (op testOp) GetKey() []byte {
|
||||
return op.Key
|
||||
}
|
||||
|
||||
func (op testOp) ProofOp() tmcrypto.ProofOp {
|
||||
bz, err := op.Proof.Marshal()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
return tmcrypto.ProofOp{
|
||||
Type: "ics23:iavl",
|
||||
Key: op.Key,
|
||||
Data: bz,
|
||||
}
|
||||
}
|
||||
|
||||
func (op testOp) Run(args [][]byte) ([][]byte, error) {
|
||||
// calculate root from proof
|
||||
root, err := op.Proof.Calculate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not calculate root for proof: %v", err)
|
||||
}
|
||||
// Only support an existence proof or nonexistence proof (batch proofs currently unsupported)
|
||||
switch len(args) {
|
||||
case 0:
|
||||
// Args are nil, so we verify the absence of the key.
|
||||
absent := ics23.VerifyNonMembership(op.Spec, root, op.Proof, op.Key)
|
||||
if !absent {
|
||||
return nil, fmt.Errorf("proof did not verify absence of key: %s", string(op.Key))
|
||||
}
|
||||
case 1:
|
||||
// Args is length 1, verify existence of key with value args[0]
|
||||
if !ics23.VerifyMembership(op.Spec, root, op.Proof, op.Key, args[0]) {
|
||||
return nil, fmt.Errorf("proof did not verify existence of key %s with given value %x", op.Key, args[0])
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("args must be length 0 or 1, got: %d", len(args))
|
||||
}
|
||||
|
||||
return [][]byte{root}, nil
|
||||
}
|
||||
|
||||
func testOpDecoder(pop tmcrypto.ProofOp) (merkle.ProofOperator, error) {
|
||||
proof := &ics23.CommitmentProof{}
|
||||
err := proof.Unmarshal(pop.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
op := testOp{
|
||||
Key: pop.Key,
|
||||
Spec: ics23.IavlSpec,
|
||||
Proof: proof,
|
||||
}
|
||||
return op, nil
|
||||
}
|
||||
22
node/node.go
22
node/node.go
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof" // nolint: gosec // securely exposed on separate, optional port
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -41,6 +40,7 @@ import (
|
||||
"github.com/tendermint/tendermint/state/indexer"
|
||||
blockidxkv "github.com/tendermint/tendermint/state/indexer/block/kv"
|
||||
blockidxnull "github.com/tendermint/tendermint/state/indexer/block/null"
|
||||
"github.com/tendermint/tendermint/state/indexer/sink/psql"
|
||||
"github.com/tendermint/tendermint/state/txindex"
|
||||
"github.com/tendermint/tendermint/state/txindex/kv"
|
||||
"github.com/tendermint/tendermint/state/txindex/null"
|
||||
@@ -49,6 +49,10 @@ import (
|
||||
"github.com/tendermint/tendermint/types"
|
||||
tmtime "github.com/tendermint/tendermint/types/time"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
|
||||
_ "net/http/pprof" // nolint: gosec // securely exposed on separate, optional port
|
||||
|
||||
_ "github.com/lib/pq" // provide the psql db driver
|
||||
)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -259,6 +263,7 @@ func createAndStartEventBus(logger log.Logger) (*types.EventBus, error) {
|
||||
|
||||
func createAndStartIndexerService(
|
||||
config *cfg.Config,
|
||||
chainID string,
|
||||
dbProvider DBProvider,
|
||||
eventBus *types.EventBus,
|
||||
logger log.Logger,
|
||||
@@ -278,6 +283,18 @@ func createAndStartIndexerService(
|
||||
|
||||
txIndexer = kv.NewTxIndex(store)
|
||||
blockIndexer = blockidxkv.New(dbm.NewPrefixDB(store, []byte("block_events")))
|
||||
|
||||
case "psql":
|
||||
if config.TxIndex.PsqlConn == "" {
|
||||
return nil, nil, nil, errors.New(`no psql-conn is set for the "psql" indexer`)
|
||||
}
|
||||
es, err := psql.NewEventSink(config.TxIndex.PsqlConn, chainID)
|
||||
if err != nil {
|
||||
return nil, nil, nil, fmt.Errorf("creating psql indexer: %w", err)
|
||||
}
|
||||
txIndexer = es.TxIndexer()
|
||||
blockIndexer = es.BlockIndexer()
|
||||
|
||||
default:
|
||||
txIndexer = &null.TxIndex{}
|
||||
blockIndexer = &blockidxnull.BlockerIndexer{}
|
||||
@@ -681,7 +698,8 @@ func NewNode(config *cfg.Config,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
indexerService, txIndexer, blockIndexer, err := createAndStartIndexerService(config, dbProvider, eventBus, logger)
|
||||
indexerService, txIndexer, blockIndexer, err := createAndStartIndexerService(config,
|
||||
genDoc.ChainID, dbProvider, eventBus, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ option go_package = "github.com/tendermint/tendermint/abci/types";
|
||||
// For more information on gogo.proto, see:
|
||||
// https://github.com/gogo/protobuf/blob/master/extensions.md
|
||||
import "tendermint/crypto/proof.proto";
|
||||
import "tendermint/types/types.proto";
|
||||
import "tendermint/crypto/keys.proto";
|
||||
import "tendermint/types/params.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
@@ -75,10 +74,13 @@ message RequestQuery {
|
||||
}
|
||||
|
||||
message RequestBeginBlock {
|
||||
bytes hash = 1;
|
||||
tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
|
||||
LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
bytes hash = 1;
|
||||
LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
|
||||
repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false];
|
||||
int64 height = 5;
|
||||
google.protobuf.Timestamp time = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
|
||||
bytes next_validators_hash = 7; // validators for the next block
|
||||
bytes proposer_address = 8;
|
||||
}
|
||||
|
||||
enum CheckTxType {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/tendermint/tendermint/abci/example/kvstore"
|
||||
"github.com/tendermint/tendermint/abci/types"
|
||||
tmsync "github.com/tendermint/tendermint/libs/sync"
|
||||
e2e "github.com/tendermint/tendermint/test/e2e/app"
|
||||
)
|
||||
|
||||
// ClientCreator creates new ABCI clients.
|
||||
@@ -79,6 +80,12 @@ func DefaultClientCreator(addr, transport, dbDir string) ClientCreator {
|
||||
return NewLocalClientCreator(kvstore.NewApplication())
|
||||
case "persistent_kvstore":
|
||||
return NewLocalClientCreator(kvstore.NewPersistentKVStoreApplication(dbDir))
|
||||
case "e2e":
|
||||
app, err := e2e.NewApplication(e2e.DefaultConfig(dbDir))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return NewLocalClientCreator(app)
|
||||
case "noop":
|
||||
return NewLocalClientCreator(types.NewBaseApplication())
|
||||
default:
|
||||
|
||||
@@ -306,9 +306,12 @@ func execBlockOnProxyApp(
|
||||
|
||||
abciResponses.BeginBlock, err = proxyAppConn.BeginBlockSync(abci.RequestBeginBlock{
|
||||
Hash: block.Hash(),
|
||||
Header: *pbh,
|
||||
LastCommitInfo: commitInfo,
|
||||
ByzantineValidators: byzVals,
|
||||
Height: pbh.Height,
|
||||
Time: pbh.Time,
|
||||
NextValidatorsHash: pbh.NextValidatorsHash,
|
||||
ProposerAddress: pbh.ProposerAddress,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("error in proxyAppConn.BeginBlock", "err", err)
|
||||
|
||||
88
state/indexer/sink/psql/backport.go
Normal file
88
state/indexer/sink/psql/backport.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package psql
|
||||
|
||||
// This file adds code to the psql package that is needed for integration with
|
||||
// v0.34, but which is not part of the original implementation.
|
||||
//
|
||||
// In v0.35, ADR 65 was implemented in which the TxIndexer and BlockIndexer
|
||||
// interfaces were merged into a hybrid EventSink interface. The Backport*
|
||||
// types defined here bridge the psql EventSink (which was built in terms of
|
||||
// the v0.35 interface) to the old interfaces.
|
||||
//
|
||||
// We took this narrower approach to backporting to avoid pulling in a much
|
||||
// wider-reaching set of changes in v0.35 that would have broken several of the
|
||||
// v0.34.x APIs. The result is sufficient to work with the node plumbing as it
|
||||
// exists in the v0.34 branch.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/pubsub/query"
|
||||
"github.com/tendermint/tendermint/state/txindex"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
eventTypeBeginBlock = "begin_block"
|
||||
eventTypeEndBlock = "end_block"
|
||||
)
|
||||
|
||||
// TxIndexer returns a bridge from es to the Tendermint v0.34 transaction indexer.
|
||||
func (es *EventSink) TxIndexer() BackportTxIndexer {
|
||||
return BackportTxIndexer{psql: es}
|
||||
}
|
||||
|
||||
// BackportTxIndexer implements the txindex.TxIndexer interface by delegating
|
||||
// indexing operations to an underlying PostgreSQL event sink.
|
||||
type BackportTxIndexer struct{ psql *EventSink }
|
||||
|
||||
// AddBatch indexes a batch of transactions in Postgres, as part of TxIndexer.
|
||||
func (b BackportTxIndexer) AddBatch(batch *txindex.Batch) error {
|
||||
return b.psql.IndexTxEvents(batch.Ops)
|
||||
}
|
||||
|
||||
// Index indexes a single transaction result in Postgres, as part of TxIndexer.
|
||||
func (b BackportTxIndexer) Index(txr *abci.TxResult) error {
|
||||
return b.psql.IndexTxEvents([]*abci.TxResult{txr})
|
||||
}
|
||||
|
||||
// Get is implemented to satisfy the TxIndexer interface, but is not supported
|
||||
// by the psql event sink and reports an error for all inputs.
|
||||
func (BackportTxIndexer) Get([]byte) (*abci.TxResult, error) {
|
||||
return nil, errors.New("the TxIndexer.Get method is not supported")
|
||||
}
|
||||
|
||||
// Search is implemented to satisfy the TxIndexer interface, but it is not
|
||||
// supported by the psql event sink and reports an error for all inputs.
|
||||
func (BackportTxIndexer) Search(context.Context, *query.Query) ([]*abci.TxResult, error) {
|
||||
return nil, errors.New("the TxIndexer.Search method is not supported")
|
||||
}
|
||||
|
||||
// BlockIndexer returns a bridge that implements the Tendermint v0.34 block
|
||||
// indexer interface, using the Postgres event sink as a backing store.
|
||||
func (es *EventSink) BlockIndexer() BackportBlockIndexer {
|
||||
return BackportBlockIndexer{psql: es}
|
||||
}
|
||||
|
||||
// BackportBlockIndexer implements the indexer.BlockIndexer interface by
|
||||
// delegating indexing operations to an underlying PostgreSQL event sink.
|
||||
type BackportBlockIndexer struct{ psql *EventSink }
|
||||
|
||||
// Has is implemented to satisfy the BlockIndexer interface, but it is not
|
||||
// supported by the psql event sink and reports an error for all inputs.
|
||||
func (BackportBlockIndexer) Has(height int64) (bool, error) {
|
||||
return false, errors.New("the BlockIndexer.Has method is not supported")
|
||||
}
|
||||
|
||||
// Index indexes block begin and end events for the specified block. It is
|
||||
// part of the BlockIndexer interface.
|
||||
func (b BackportBlockIndexer) Index(block types.EventDataNewBlockHeader) error {
|
||||
return b.psql.IndexBlockEvents(block)
|
||||
}
|
||||
|
||||
// Search is implemented to satisfy the BlockIndexer interface, but it is not
|
||||
// supported by the psql event sink and reports an error for all inputs.
|
||||
func (BackportBlockIndexer) Search(context.Context, *query.Query) ([]int64, error) {
|
||||
return nil, errors.New("the BlockIndexer.Search method is not supported")
|
||||
}
|
||||
11
state/indexer/sink/psql/backport_test.go
Normal file
11
state/indexer/sink/psql/backport_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"github.com/tendermint/tendermint/state/indexer"
|
||||
"github.com/tendermint/tendermint/state/txindex"
|
||||
)
|
||||
|
||||
var (
|
||||
_ indexer.BlockIndexer = BackportBlockIndexer{}
|
||||
_ txindex.TxIndexer = BackportTxIndexer{}
|
||||
)
|
||||
253
state/indexer/sink/psql/psql.go
Normal file
253
state/indexer/sink/psql/psql.go
Normal file
@@ -0,0 +1,253 @@
|
||||
// Package psql implements an event sink backed by a PostgreSQL database.
|
||||
package psql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/pubsub/query"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
tableBlocks = "blocks"
|
||||
tableTxResults = "tx_results"
|
||||
tableEvents = "events"
|
||||
tableAttributes = "attributes"
|
||||
driverName = "postgres"
|
||||
)
|
||||
|
||||
// EventSink is an indexer backend providing the tx/block index services. This
|
||||
// implementation stores records in a PostgreSQL database using the schema
|
||||
// defined in state/indexer/sink/psql/schema.sql.
|
||||
type EventSink struct {
|
||||
store *sql.DB
|
||||
chainID string
|
||||
}
|
||||
|
||||
// NewEventSink constructs an event sink associated with the PostgreSQL
|
||||
// database specified by connStr. Events written to the sink are attributed to
|
||||
// the specified chainID.
|
||||
func NewEventSink(connStr, chainID string) (*EventSink, error) {
|
||||
db, err := sql.Open(driverName, connStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &EventSink{
|
||||
store: db,
|
||||
chainID: chainID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DB returns the underlying Postgres connection used by the sink.
|
||||
// This is exported to support testing.
|
||||
func (es *EventSink) DB() *sql.DB { return es.store }
|
||||
|
||||
// runInTransaction executes query in a fresh database transaction.
|
||||
// If query reports an error, the transaction is rolled back and the
|
||||
// error from query is reported to the caller.
|
||||
// Otherwise, the result of committing the transaction is returned.
|
||||
func runInTransaction(db *sql.DB, query func(*sql.Tx) error) error {
|
||||
dbtx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := query(dbtx); err != nil {
|
||||
_ = dbtx.Rollback() // report the initial error, not the rollback
|
||||
return err
|
||||
}
|
||||
return dbtx.Commit()
|
||||
}
|
||||
|
||||
// queryWithID executes the specified SQL query with the given arguments,
|
||||
// expecting a single-row, single-column result containing an ID. If the query
|
||||
// succeeds, the ID from the result is returned.
|
||||
func queryWithID(tx *sql.Tx, query string, args ...interface{}) (uint32, error) {
|
||||
var id uint32
|
||||
if err := tx.QueryRow(query, args...).Scan(&id); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// insertEvents inserts a slice of events and any indexed attributes of those
|
||||
// events into the database associated with dbtx.
|
||||
//
|
||||
// If txID > 0, the event is attributed to the Tendermint transaction with that
|
||||
// ID; otherwise it is recorded as a block event.
|
||||
func insertEvents(dbtx *sql.Tx, blockID, txID uint32, evts []abci.Event) error {
|
||||
// Populate the transaction ID field iff one is defined (> 0).
|
||||
var txIDArg interface{}
|
||||
if txID > 0 {
|
||||
txIDArg = txID
|
||||
}
|
||||
|
||||
// Add each event to the events table, and retrieve its row ID to use when
|
||||
// adding any attributes the event provides.
|
||||
for _, evt := range evts {
|
||||
// Skip events with an empty type.
|
||||
if evt.Type == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
eid, err := queryWithID(dbtx, `
|
||||
INSERT INTO `+tableEvents+` (block_id, tx_id, type) VALUES ($1, $2, $3)
|
||||
RETURNING rowid;
|
||||
`, blockID, txIDArg, evt.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Add any attributes flagged for indexing.
|
||||
for _, attr := range evt.Attributes {
|
||||
if !attr.Index {
|
||||
continue
|
||||
}
|
||||
compositeKey := evt.Type + "." + string(attr.Key)
|
||||
if _, err := dbtx.Exec(`
|
||||
INSERT INTO `+tableAttributes+` (event_id, key, composite_key, value)
|
||||
VALUES ($1, $2, $3, $4);
|
||||
`, eid, attr.Key, compositeKey, attr.Value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// makeIndexedEvent constructs an event from the specified composite key and
|
||||
// value. If the key has the form "type.name", the event will have a single
|
||||
// attribute with that name and the value; otherwise the event will have only
|
||||
// a type and no attributes.
|
||||
func makeIndexedEvent(compositeKey, value string) abci.Event {
|
||||
i := strings.Index(compositeKey, ".")
|
||||
if i < 0 {
|
||||
return abci.Event{Type: compositeKey}
|
||||
}
|
||||
return abci.Event{Type: compositeKey[:i], Attributes: []abci.EventAttribute{
|
||||
{Key: []byte(compositeKey[i+1:]), Value: []byte(value), Index: true},
|
||||
}}
|
||||
}
|
||||
|
||||
// IndexBlockEvents indexes the specified block header, part of the
|
||||
// indexer.EventSink interface.
|
||||
func (es *EventSink) IndexBlockEvents(h types.EventDataNewBlockHeader) error {
|
||||
ts := time.Now().UTC()
|
||||
|
||||
return runInTransaction(es.store, func(dbtx *sql.Tx) error {
|
||||
// Add the block to the blocks table and report back its row ID for use
|
||||
// in indexing the events for the block.
|
||||
blockID, err := queryWithID(dbtx, `
|
||||
INSERT INTO `+tableBlocks+` (height, chain_id, created_at)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT DO NOTHING
|
||||
RETURNING rowid;
|
||||
`, h.Header.Height, es.chainID, ts)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil // we already saw this block; quietly succeed
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("indexing block header: %w", err)
|
||||
}
|
||||
|
||||
// Insert the special block meta-event for height.
|
||||
if err := insertEvents(dbtx, blockID, 0, []abci.Event{
|
||||
makeIndexedEvent(types.BlockHeightKey, fmt.Sprint(h.Header.Height)),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("block meta-events: %w", err)
|
||||
}
|
||||
// Insert all the block events. Order is important here,
|
||||
if err := insertEvents(dbtx, blockID, 0, h.ResultBeginBlock.Events); err != nil {
|
||||
return fmt.Errorf("begin-block events: %w", err)
|
||||
}
|
||||
if err := insertEvents(dbtx, blockID, 0, h.ResultEndBlock.Events); err != nil {
|
||||
return fmt.Errorf("end-block events: %w", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (es *EventSink) IndexTxEvents(txrs []*abci.TxResult) error {
|
||||
ts := time.Now().UTC()
|
||||
|
||||
for _, txr := range txrs {
|
||||
// Encode the result message in protobuf wire format for indexing.
|
||||
resultData, err := proto.Marshal(txr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshaling tx_result: %w", err)
|
||||
}
|
||||
|
||||
// Index the hash of the underlying transaction as a hex string.
|
||||
txHash := fmt.Sprintf("%X", types.Tx(txr.Tx).Hash())
|
||||
|
||||
if err := runInTransaction(es.store, func(dbtx *sql.Tx) error {
|
||||
// Find the block associated with this transaction. The block header
|
||||
// must have been indexed prior to the transactions belonging to it.
|
||||
blockID, err := queryWithID(dbtx, `
|
||||
SELECT rowid FROM `+tableBlocks+` WHERE height = $1 AND chain_id = $2;
|
||||
`, txr.Height, es.chainID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("finding block ID: %w", err)
|
||||
}
|
||||
|
||||
// Insert a record for this tx_result and capture its ID for indexing events.
|
||||
txID, err := queryWithID(dbtx, `
|
||||
INSERT INTO `+tableTxResults+` (block_id, index, created_at, tx_hash, tx_result)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
ON CONFLICT DO NOTHING
|
||||
RETURNING rowid;
|
||||
`, blockID, txr.Index, ts, txHash, resultData)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil // we already saw this transaction; quietly succeed
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("indexing tx_result: %w", err)
|
||||
}
|
||||
|
||||
// Insert the special transaction meta-events for hash and height.
|
||||
if err := insertEvents(dbtx, blockID, txID, []abci.Event{
|
||||
makeIndexedEvent(types.TxHashKey, txHash),
|
||||
makeIndexedEvent(types.TxHeightKey, fmt.Sprint(txr.Height)),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("indexing transaction meta-events: %w", err)
|
||||
}
|
||||
// Index any events packaged with the transaction.
|
||||
if err := insertEvents(dbtx, blockID, txID, txr.Result.Events); err != nil {
|
||||
return fmt.Errorf("indexing transaction events: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SearchBlockEvents is not implemented by this sink, and reports an error for all queries.
|
||||
func (es *EventSink) SearchBlockEvents(ctx context.Context, q *query.Query) ([]int64, error) {
|
||||
return nil, errors.New("block search is not supported via the postgres event sink")
|
||||
}
|
||||
|
||||
// SearchTxEvents is not implemented by this sink, and reports an error for all queries.
|
||||
func (es *EventSink) SearchTxEvents(ctx context.Context, q *query.Query) ([]*abci.TxResult, error) {
|
||||
return nil, errors.New("tx search is not supported via the postgres event sink")
|
||||
}
|
||||
|
||||
// GetTxByHash is not implemented by this sink, and reports an error for all queries.
|
||||
func (es *EventSink) GetTxByHash(hash []byte) (*abci.TxResult, error) {
|
||||
return nil, errors.New("getTxByHash is not supported via the postgres event sink")
|
||||
}
|
||||
|
||||
// HasBlock is not implemented by this sink, and reports an error for all queries.
|
||||
func (es *EventSink) HasBlock(h int64) (bool, error) {
|
||||
return false, errors.New("hasBlock is not supported via the postgres event sink")
|
||||
}
|
||||
|
||||
// Stop closes the underlying PostgreSQL database.
|
||||
func (es *EventSink) Stop() error { return es.store.Close() }
|
||||
341
state/indexer/sink/psql/psql_test.go
Normal file
341
state/indexer/sink/psql/psql_test.go
Normal file
@@ -0,0 +1,341 @@
|
||||
package psql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/adlio/schema"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/ory/dockertest"
|
||||
"github.com/ory/dockertest/docker"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
|
||||
// Register the Postgres database driver.
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var (
|
||||
doPauseAtExit = flag.Bool("pause-at-exit", false,
|
||||
"If true, pause the test until interrupted at shutdown, to allow debugging")
|
||||
|
||||
// A hook that test cases can call to obtain the shared database instance
|
||||
// used for testing the sink. This is initialized in TestMain (see below).
|
||||
testDB func() *sql.DB
|
||||
)
|
||||
|
||||
const (
|
||||
user = "postgres"
|
||||
password = "secret"
|
||||
port = "5432"
|
||||
dsn = "postgres://%s:%s@localhost:%s/%s?sslmode=disable"
|
||||
dbName = "postgres"
|
||||
chainID = "test-chainID"
|
||||
|
||||
viewBlockEvents = "block_events"
|
||||
viewTxEvents = "tx_events"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
|
||||
// Set up docker and start a container running PostgreSQL.
|
||||
pool, err := dockertest.NewPool(os.Getenv("DOCKER_URL"))
|
||||
if err != nil {
|
||||
log.Fatalf("Creating docker pool: %v", err)
|
||||
}
|
||||
|
||||
resource, err := pool.RunWithOptions(&dockertest.RunOptions{
|
||||
Repository: "postgres",
|
||||
Tag: "13",
|
||||
Env: []string{
|
||||
"POSTGRES_USER=" + user,
|
||||
"POSTGRES_PASSWORD=" + password,
|
||||
"POSTGRES_DB=" + dbName,
|
||||
"listen_addresses = '*'",
|
||||
},
|
||||
ExposedPorts: []string{port},
|
||||
}, func(config *docker.HostConfig) {
|
||||
// set AutoRemove to true so that stopped container goes away by itself
|
||||
config.AutoRemove = true
|
||||
config.RestartPolicy = docker.RestartPolicy{
|
||||
Name: "no",
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Starting docker pool: %v", err)
|
||||
}
|
||||
|
||||
if *doPauseAtExit {
|
||||
log.Print("Pause at exit is enabled, containers will not expire")
|
||||
} else {
|
||||
const expireSeconds = 60
|
||||
_ = resource.Expire(expireSeconds)
|
||||
log.Printf("Container expiration set to %d seconds", expireSeconds)
|
||||
}
|
||||
|
||||
// Connect to the database, clear any leftover data, and install the
|
||||
// indexing schema.
|
||||
conn := fmt.Sprintf(dsn, user, password, resource.GetPort(port+"/tcp"), dbName)
|
||||
var db *sql.DB
|
||||
|
||||
if err := pool.Retry(func() error {
|
||||
sink, err := NewEventSink(conn, chainID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db = sink.DB() // set global for test use
|
||||
return db.Ping()
|
||||
}); err != nil {
|
||||
log.Fatalf("Connecting to database: %v", err)
|
||||
}
|
||||
|
||||
if err := resetDatabase(db); err != nil {
|
||||
log.Fatalf("Flushing database: %v", err)
|
||||
}
|
||||
|
||||
sm, err := readSchema()
|
||||
if err != nil {
|
||||
log.Fatalf("Reading schema: %v", err)
|
||||
} else if err := schema.NewMigrator().Apply(db, sm); err != nil {
|
||||
log.Fatalf("Applying schema: %v", err)
|
||||
}
|
||||
|
||||
// Set up the hook for tests to get the shared database handle.
|
||||
testDB = func() *sql.DB { return db }
|
||||
|
||||
// Run the selected test cases.
|
||||
code := m.Run()
|
||||
|
||||
// Clean up and shut down the database container.
|
||||
if *doPauseAtExit {
|
||||
log.Print("Testing complete, pausing for inspection. Send SIGINT to resume teardown")
|
||||
waitForInterrupt()
|
||||
log.Print("(resuming)")
|
||||
}
|
||||
log.Print("Shutting down database")
|
||||
if err := pool.Purge(resource); err != nil {
|
||||
log.Printf("WARNING: Purging pool failed: %v", err)
|
||||
}
|
||||
if err := db.Close(); err != nil {
|
||||
log.Printf("WARNING: Closing database failed: %v", err)
|
||||
}
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func TestIndexing(t *testing.T) {
|
||||
t.Run("IndexBlockEvents", func(t *testing.T) {
|
||||
indexer := &EventSink{store: testDB(), chainID: chainID}
|
||||
require.NoError(t, indexer.IndexBlockEvents(newTestBlockHeader()))
|
||||
|
||||
verifyBlock(t, 1)
|
||||
verifyBlock(t, 2)
|
||||
|
||||
verifyNotImplemented(t, "hasBlock", func() (bool, error) { return indexer.HasBlock(1) })
|
||||
verifyNotImplemented(t, "hasBlock", func() (bool, error) { return indexer.HasBlock(2) })
|
||||
|
||||
verifyNotImplemented(t, "block search", func() (bool, error) {
|
||||
v, err := indexer.SearchBlockEvents(context.Background(), nil)
|
||||
return v != nil, err
|
||||
})
|
||||
|
||||
require.NoError(t, verifyTimeStamp(tableBlocks))
|
||||
|
||||
// Attempting to reindex the same events should gracefully succeed.
|
||||
require.NoError(t, indexer.IndexBlockEvents(newTestBlockHeader()))
|
||||
})
|
||||
|
||||
t.Run("IndexTxEvents", func(t *testing.T) {
|
||||
indexer := &EventSink{store: testDB(), chainID: chainID}
|
||||
|
||||
txResult := txResultWithEvents([]abci.Event{
|
||||
makeIndexedEvent("account.number", "1"),
|
||||
makeIndexedEvent("account.owner", "Ivan"),
|
||||
makeIndexedEvent("account.owner", "Yulieta"),
|
||||
|
||||
{Type: "", Attributes: []abci.EventAttribute{
|
||||
{
|
||||
Key: []byte("not_allowed"),
|
||||
Value: []byte("Vlad"),
|
||||
Index: true,
|
||||
},
|
||||
}},
|
||||
})
|
||||
require.NoError(t, indexer.IndexTxEvents([]*abci.TxResult{txResult}))
|
||||
|
||||
txr, err := loadTxResult(types.Tx(txResult.Tx).Hash())
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, txResult, txr)
|
||||
|
||||
require.NoError(t, verifyTimeStamp(tableTxResults))
|
||||
require.NoError(t, verifyTimeStamp(viewTxEvents))
|
||||
|
||||
verifyNotImplemented(t, "getTxByHash", func() (bool, error) {
|
||||
txr, err := indexer.GetTxByHash(types.Tx(txResult.Tx).Hash())
|
||||
return txr != nil, err
|
||||
})
|
||||
verifyNotImplemented(t, "tx search", func() (bool, error) {
|
||||
txr, err := indexer.SearchTxEvents(context.Background(), nil)
|
||||
return txr != nil, err
|
||||
})
|
||||
|
||||
// try to insert the duplicate tx events.
|
||||
err = indexer.IndexTxEvents([]*abci.TxResult{txResult})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestStop(t *testing.T) {
|
||||
indexer := &EventSink{store: testDB()}
|
||||
require.NoError(t, indexer.Stop())
|
||||
}
|
||||
|
||||
// newTestBlockHeader constructs a fresh copy of a block header containing
|
||||
// known test values to exercise the indexer.
|
||||
func newTestBlockHeader() types.EventDataNewBlockHeader {
|
||||
return types.EventDataNewBlockHeader{
|
||||
Header: types.Header{Height: 1},
|
||||
ResultBeginBlock: abci.ResponseBeginBlock{
|
||||
Events: []abci.Event{
|
||||
makeIndexedEvent("begin_event.proposer", "FCAA001"),
|
||||
makeIndexedEvent("thingy.whatzit", "O.O"),
|
||||
},
|
||||
},
|
||||
ResultEndBlock: abci.ResponseEndBlock{
|
||||
Events: []abci.Event{
|
||||
makeIndexedEvent("end_event.foo", "100"),
|
||||
makeIndexedEvent("thingy.whatzit", "-.O"),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// readSchema loads the indexing database schema file
|
||||
func readSchema() ([]*schema.Migration, error) {
|
||||
const filename = "schema.sql"
|
||||
contents, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read sql file from '%s': %w", filename, err)
|
||||
}
|
||||
|
||||
return []*schema.Migration{{
|
||||
ID: time.Now().Local().String() + " db schema",
|
||||
Script: string(contents),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
// resetDB drops all the data from the test database.
|
||||
func resetDatabase(db *sql.DB) error {
|
||||
_, err := db.Exec(`DROP TABLE IF EXISTS blocks,tx_results,events,attributes CASCADE;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dropping tables: %v", err)
|
||||
}
|
||||
_, err = db.Exec(`DROP VIEW IF EXISTS event_attributes,block_events,tx_events CASCADE;`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dropping views: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// txResultWithEvents constructs a fresh transaction result with fixed values
|
||||
// for testing, that includes the specified events.
|
||||
func txResultWithEvents(events []abci.Event) *abci.TxResult {
|
||||
return &abci.TxResult{
|
||||
Height: 1,
|
||||
Index: 0,
|
||||
Tx: types.Tx("HELLO WORLD"),
|
||||
Result: abci.ResponseDeliverTx{
|
||||
Data: []byte{0},
|
||||
Code: abci.CodeTypeOK,
|
||||
Log: "",
|
||||
Events: events,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func loadTxResult(hash []byte) (*abci.TxResult, error) {
|
||||
hashString := fmt.Sprintf("%X", hash)
|
||||
var resultData []byte
|
||||
if err := testDB().QueryRow(`
|
||||
SELECT tx_result FROM `+tableTxResults+` WHERE tx_hash = $1;
|
||||
`, hashString).Scan(&resultData); err != nil {
|
||||
return nil, fmt.Errorf("lookup transaction for hash %q failed: %v", hashString, err)
|
||||
}
|
||||
|
||||
txr := new(abci.TxResult)
|
||||
if err := proto.Unmarshal(resultData, txr); err != nil {
|
||||
return nil, fmt.Errorf("unmarshaling txr: %v", err)
|
||||
}
|
||||
|
||||
return txr, nil
|
||||
}
|
||||
|
||||
func verifyTimeStamp(tableName string) error {
|
||||
return testDB().QueryRow(fmt.Sprintf(`
|
||||
SELECT DISTINCT %[1]s.created_at
|
||||
FROM %[1]s
|
||||
WHERE %[1]s.created_at >= $1;
|
||||
`, tableName), time.Now().Add(-2*time.Second)).Err()
|
||||
}
|
||||
|
||||
func verifyBlock(t *testing.T, height int64) {
|
||||
// Check that the blocks table contains an entry for this height.
|
||||
if err := testDB().QueryRow(`
|
||||
SELECT height FROM `+tableBlocks+` WHERE height = $1;
|
||||
`, height).Err(); err == sql.ErrNoRows {
|
||||
t.Errorf("No block found for height=%d", height)
|
||||
} else if err != nil {
|
||||
t.Fatalf("Database query failed: %v", err)
|
||||
}
|
||||
|
||||
// Verify the presence of begin_block and end_block events.
|
||||
if err := testDB().QueryRow(`
|
||||
SELECT type, height, chain_id FROM `+viewBlockEvents+`
|
||||
WHERE height = $1 AND type = $2 AND chain_id = $3;
|
||||
`, height, eventTypeBeginBlock, chainID).Err(); err == sql.ErrNoRows {
|
||||
t.Errorf("No %q event found for height=%d", eventTypeBeginBlock, height)
|
||||
} else if err != nil {
|
||||
t.Fatalf("Database query failed: %v", err)
|
||||
}
|
||||
|
||||
if err := testDB().QueryRow(`
|
||||
SELECT type, height, chain_id FROM `+viewBlockEvents+`
|
||||
WHERE height = $1 AND type = $2 AND chain_id = $3;
|
||||
`, height, eventTypeEndBlock, chainID).Err(); err == sql.ErrNoRows {
|
||||
t.Errorf("No %q event found for height=%d", eventTypeEndBlock, height)
|
||||
} else if err != nil {
|
||||
t.Fatalf("Database query failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// verifyNotImplemented calls f and verifies that it returns both a
|
||||
// false-valued flag and a non-nil error whose string matching the expected
|
||||
// "not supported" message with label prefixed.
|
||||
func verifyNotImplemented(t *testing.T, label string, f func() (bool, error)) {
|
||||
t.Helper()
|
||||
t.Logf("Verifying that %q reports it is not implemented", label)
|
||||
|
||||
want := label + " is not supported via the postgres event sink"
|
||||
ok, err := f()
|
||||
assert.False(t, ok)
|
||||
require.NotNil(t, err)
|
||||
assert.Equal(t, want, err.Error())
|
||||
}
|
||||
|
||||
// waitForInterrupt blocks until a SIGINT is received by the process.
|
||||
func waitForInterrupt() {
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, os.Interrupt)
|
||||
<-ch
|
||||
}
|
||||
85
state/indexer/sink/psql/schema.sql
Normal file
85
state/indexer/sink/psql/schema.sql
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
This file defines the database schema for the PostgresQL ("psql") event sink
|
||||
implementation in Tendermint. The operator must create a database and install
|
||||
this schema before using the database to index events.
|
||||
*/
|
||||
|
||||
-- The blocks table records metadata about each block.
|
||||
-- The block record does not include its events or transactions (see tx_results).
|
||||
CREATE TABLE blocks (
|
||||
rowid BIGSERIAL PRIMARY KEY,
|
||||
|
||||
height BIGINT NOT NULL,
|
||||
chain_id VARCHAR NOT NULL,
|
||||
|
||||
-- When this block header was logged into the sink, in UTC.
|
||||
created_at TIMESTAMPTZ NOT NULL,
|
||||
|
||||
UNIQUE (height, chain_id)
|
||||
);
|
||||
|
||||
-- Index blocks by height and chain, since we need to resolve block IDs when
|
||||
-- indexing transaction records and transaction events.
|
||||
CREATE INDEX idx_blocks_height_chain ON blocks(height, chain_id);
|
||||
|
||||
-- The tx_results table records metadata about transaction results. Note that
|
||||
-- the events from a transaction are stored separately.
|
||||
CREATE TABLE tx_results (
|
||||
rowid BIGSERIAL PRIMARY KEY,
|
||||
|
||||
-- The block to which this transaction belongs.
|
||||
block_id BIGINT NOT NULL REFERENCES blocks(rowid),
|
||||
-- The sequential index of the transaction within the block.
|
||||
index INTEGER NOT NULL,
|
||||
-- When this result record was logged into the sink, in UTC.
|
||||
created_at TIMESTAMPTZ NOT NULL,
|
||||
-- The hex-encoded hash of the transaction.
|
||||
tx_hash VARCHAR NOT NULL,
|
||||
-- The protobuf wire encoding of the TxResult message.
|
||||
tx_result BYTEA NOT NULL,
|
||||
|
||||
UNIQUE (block_id, index)
|
||||
);
|
||||
|
||||
-- The events table records events. All events (both block and transaction) are
|
||||
-- associated with a block ID; transaction events also have a transaction ID.
|
||||
CREATE TABLE events (
|
||||
rowid BIGSERIAL PRIMARY KEY,
|
||||
|
||||
-- The block and transaction this event belongs to.
|
||||
-- If tx_id is NULL, this is a block event.
|
||||
block_id BIGINT NOT NULL REFERENCES blocks(rowid),
|
||||
tx_id BIGINT NULL REFERENCES tx_results(rowid),
|
||||
|
||||
-- The application-defined type label for the event.
|
||||
type VARCHAR NOT NULL
|
||||
);
|
||||
|
||||
-- The attributes table records event attributes.
|
||||
CREATE TABLE attributes (
|
||||
event_id BIGINT NOT NULL REFERENCES events(rowid),
|
||||
key VARCHAR NOT NULL, -- bare key
|
||||
composite_key VARCHAR NOT NULL, -- composed type.key
|
||||
value VARCHAR NULL,
|
||||
|
||||
UNIQUE (event_id, key)
|
||||
);
|
||||
|
||||
-- A joined view of events and their attributes. Events that do not have any
|
||||
-- attributes are represented as a single row with empty key and value fields.
|
||||
CREATE VIEW event_attributes AS
|
||||
SELECT block_id, tx_id, type, key, composite_key, value
|
||||
FROM events LEFT JOIN attributes ON (events.rowid = attributes.event_id);
|
||||
|
||||
-- A joined view of all block events (those having tx_id NULL).
|
||||
CREATE VIEW block_events AS
|
||||
SELECT blocks.rowid as block_id, height, chain_id, type, key, composite_key, value
|
||||
FROM blocks JOIN event_attributes ON (blocks.rowid = event_attributes.block_id)
|
||||
WHERE event_attributes.tx_id IS NULL;
|
||||
|
||||
-- A joined view of all transaction events.
|
||||
CREATE VIEW tx_events AS
|
||||
SELECT height, index, chain_id, type, key, composite_key, value, tx_results.created_at
|
||||
FROM blocks JOIN tx_results ON (blocks.rowid = tx_results.block_id)
|
||||
JOIN event_attributes ON (tx_results.rowid = event_attributes.tx_id)
|
||||
WHERE event_attributes.tx_id IS NOT NULL;
|
||||
194
state/mocks/block_store.go
Normal file
194
state/mocks/block_store.go
Normal file
@@ -0,0 +1,194 @@
|
||||
// Code generated by mockery 2.9.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
types "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
// BlockStore is an autogenerated mock type for the BlockStore type
|
||||
type BlockStore struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Base provides a mock function with given fields:
|
||||
func (_m *BlockStore) Base() int64 {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Height provides a mock function with given fields:
|
||||
func (_m *BlockStore) Height() int64 {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBaseMeta provides a mock function with given fields:
|
||||
func (_m *BlockStore) LoadBaseMeta() *types.BlockMeta {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 *types.BlockMeta
|
||||
if rf, ok := ret.Get(0).(func() *types.BlockMeta); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.BlockMeta)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlock provides a mock function with given fields: height
|
||||
func (_m *BlockStore) LoadBlock(height int64) *types.Block {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 *types.Block
|
||||
if rf, ok := ret.Get(0).(func(int64) *types.Block); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.Block)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockByHash provides a mock function with given fields: hash
|
||||
func (_m *BlockStore) LoadBlockByHash(hash []byte) *types.Block {
|
||||
ret := _m.Called(hash)
|
||||
|
||||
var r0 *types.Block
|
||||
if rf, ok := ret.Get(0).(func([]byte) *types.Block); ok {
|
||||
r0 = rf(hash)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.Block)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockCommit provides a mock function with given fields: height
|
||||
func (_m *BlockStore) LoadBlockCommit(height int64) *types.Commit {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 *types.Commit
|
||||
if rf, ok := ret.Get(0).(func(int64) *types.Commit); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.Commit)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockMeta provides a mock function with given fields: height
|
||||
func (_m *BlockStore) LoadBlockMeta(height int64) *types.BlockMeta {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 *types.BlockMeta
|
||||
if rf, ok := ret.Get(0).(func(int64) *types.BlockMeta); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.BlockMeta)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadBlockPart provides a mock function with given fields: height, index
|
||||
func (_m *BlockStore) LoadBlockPart(height int64, index int) *types.Part {
|
||||
ret := _m.Called(height, index)
|
||||
|
||||
var r0 *types.Part
|
||||
if rf, ok := ret.Get(0).(func(int64, int) *types.Part); ok {
|
||||
r0 = rf(height, index)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.Part)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// LoadSeenCommit provides a mock function with given fields: height
|
||||
func (_m *BlockStore) LoadSeenCommit(height int64) *types.Commit {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 *types.Commit
|
||||
if rf, ok := ret.Get(0).(func(int64) *types.Commit); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*types.Commit)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// PruneBlocks provides a mock function with given fields: height
|
||||
func (_m *BlockStore) PruneBlocks(height int64) (uint64, error) {
|
||||
ret := _m.Called(height)
|
||||
|
||||
var r0 uint64
|
||||
if rf, ok := ret.Get(0).(func(int64) uint64); ok {
|
||||
r0 = rf(height)
|
||||
} else {
|
||||
r0 = ret.Get(0).(uint64)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(int64) error); ok {
|
||||
r1 = rf(height)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// SaveBlock provides a mock function with given fields: block, blockParts, seenCommit
|
||||
func (_m *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, seenCommit *types.Commit) {
|
||||
_m.Called(block, blockParts, seenCommit)
|
||||
}
|
||||
|
||||
// Size provides a mock function with given fields:
|
||||
func (_m *BlockStore) Size() int64 {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 int64
|
||||
if rf, ok := ret.Get(0).(func() int64); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(int64)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.1.0. DO NOT EDIT.
|
||||
// Code generated by mockery 2.9.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated by mockery v2.1.0. DO NOT EDIT.
|
||||
// Code generated by mockery 2.9.0. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
||||
89
state/rollback.go
Normal file
89
state/rollback.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
// Rollback overwrites the current Tendermint state (height n) with the most
|
||||
// recent previous state (height n - 1).
|
||||
// Note that this function does not affect application state.
|
||||
func Rollback(bs BlockStore, ss Store) (int64, []byte, error) {
|
||||
invalidState, err := ss.Load()
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
if invalidState.IsEmpty() {
|
||||
return -1, nil, errors.New("no state found")
|
||||
}
|
||||
|
||||
rollbackHeight := invalidState.LastBlockHeight
|
||||
rollbackBlock := bs.LoadBlockMeta(rollbackHeight)
|
||||
if rollbackBlock == nil {
|
||||
return -1, nil, fmt.Errorf("block at height %d not found", rollbackHeight)
|
||||
}
|
||||
|
||||
previousValidatorSet, err := ss.LoadValidators(rollbackHeight - 1)
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
previousParams, err := ss.LoadConsensusParams(rollbackHeight)
|
||||
if err != nil {
|
||||
return -1, nil, err
|
||||
}
|
||||
|
||||
valChangeHeight := invalidState.LastHeightValidatorsChanged
|
||||
// this can only happen if the validator set changed since the last block
|
||||
if valChangeHeight > rollbackHeight {
|
||||
valChangeHeight = rollbackHeight
|
||||
}
|
||||
|
||||
paramsChangeHeight := invalidState.LastHeightConsensusParamsChanged
|
||||
// this can only happen if params changed from the last block
|
||||
if paramsChangeHeight > rollbackHeight {
|
||||
paramsChangeHeight = rollbackHeight
|
||||
}
|
||||
|
||||
// build the new state from the old state and the prior block
|
||||
rolledBackState := State{
|
||||
Version: tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: previousParams.Version.AppVersion,
|
||||
},
|
||||
Software: version.TMCoreSemVer,
|
||||
},
|
||||
// immutable fields
|
||||
ChainID: invalidState.ChainID,
|
||||
InitialHeight: invalidState.InitialHeight,
|
||||
|
||||
LastBlockHeight: invalidState.LastBlockHeight - 1,
|
||||
LastBlockID: rollbackBlock.Header.LastBlockID,
|
||||
LastBlockTime: rollbackBlock.Header.Time,
|
||||
|
||||
NextValidators: invalidState.Validators,
|
||||
Validators: invalidState.LastValidators,
|
||||
LastValidators: previousValidatorSet,
|
||||
LastHeightValidatorsChanged: valChangeHeight,
|
||||
|
||||
ConsensusParams: previousParams,
|
||||
LastHeightConsensusParamsChanged: paramsChangeHeight,
|
||||
|
||||
LastResultsHash: rollbackBlock.Header.LastResultsHash,
|
||||
AppHash: rollbackBlock.Header.AppHash,
|
||||
}
|
||||
|
||||
// persist the new state. This overrides the invalid one. NOTE: this will also
|
||||
// persist the validator set and consensus params over the existing structures,
|
||||
// but both should be the same
|
||||
if err := ss.Save(rolledBackState); err != nil {
|
||||
return -1, nil, fmt.Errorf("failed to save rolled back state: %w", err)
|
||||
}
|
||||
|
||||
return rolledBackState.LastBlockHeight, rolledBackState.AppHash, nil
|
||||
}
|
||||
165
state/rollback_test.go
Normal file
165
state/rollback_test.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package state_test
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/tendermint/tendermint/crypto/tmhash"
|
||||
tmstate "github.com/tendermint/tendermint/proto/tendermint/state"
|
||||
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
|
||||
"github.com/tendermint/tendermint/state"
|
||||
"github.com/tendermint/tendermint/state/mocks"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
"github.com/tendermint/tendermint/version"
|
||||
)
|
||||
|
||||
func TestRollback(t *testing.T) {
|
||||
stateStore := state.NewStore(dbm.NewMemDB())
|
||||
blockStore := &mocks.BlockStore{}
|
||||
var (
|
||||
height int64 = 100
|
||||
appVersion uint64 = 10
|
||||
)
|
||||
|
||||
valSet, _ := types.RandValidatorSet(5, 10)
|
||||
|
||||
params := types.DefaultConsensusParams()
|
||||
params.Version.AppVersion = appVersion
|
||||
newParams := types.DefaultConsensusParams()
|
||||
newParams.Block.MaxBytes = 10000
|
||||
|
||||
initialState := state.State{
|
||||
Version: tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: 10,
|
||||
},
|
||||
Software: version.TMCoreSemVer,
|
||||
},
|
||||
ChainID: "test-chain",
|
||||
InitialHeight: 10,
|
||||
LastBlockID: makeBlockIDRandom(),
|
||||
AppHash: tmhash.Sum([]byte("app_hash")),
|
||||
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
|
||||
LastBlockHeight: height,
|
||||
LastValidators: valSet,
|
||||
Validators: valSet.CopyIncrementProposerPriority(1),
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(2),
|
||||
LastHeightValidatorsChanged: height + 1,
|
||||
ConsensusParams: *params,
|
||||
LastHeightConsensusParamsChanged: height + 1,
|
||||
}
|
||||
require.NoError(t, stateStore.Bootstrap(initialState))
|
||||
|
||||
height++
|
||||
block := &types.BlockMeta{
|
||||
Header: types.Header{
|
||||
Height: height,
|
||||
AppHash: initialState.AppHash,
|
||||
LastBlockID: initialState.LastBlockID,
|
||||
LastResultsHash: initialState.LastResultsHash,
|
||||
},
|
||||
}
|
||||
blockStore.On("LoadBlockMeta", height).Return(block)
|
||||
|
||||
appVersion++
|
||||
newParams.Version.AppVersion = appVersion
|
||||
nextState := initialState.Copy()
|
||||
nextState.LastBlockHeight = height
|
||||
nextState.Version.Consensus.App = appVersion
|
||||
nextState.LastBlockID = makeBlockIDRandom()
|
||||
nextState.AppHash = tmhash.Sum([]byte("next_app_hash"))
|
||||
nextState.LastValidators = initialState.Validators
|
||||
nextState.Validators = initialState.NextValidators
|
||||
nextState.NextValidators = initialState.NextValidators.CopyIncrementProposerPriority(1)
|
||||
nextState.ConsensusParams = *newParams
|
||||
nextState.LastHeightConsensusParamsChanged = height + 1
|
||||
nextState.LastHeightValidatorsChanged = height + 1
|
||||
|
||||
// update the state
|
||||
require.NoError(t, stateStore.Save(nextState))
|
||||
|
||||
// rollback the state
|
||||
rollbackHeight, rollbackHash, err := state.Rollback(blockStore, stateStore)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, int64(100), rollbackHeight)
|
||||
require.EqualValues(t, initialState.AppHash, rollbackHash)
|
||||
blockStore.AssertExpectations(t)
|
||||
|
||||
// assert that we've recovered the prior state
|
||||
loadedState, err := stateStore.Load()
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, initialState, loadedState)
|
||||
}
|
||||
|
||||
func TestRollbackNoState(t *testing.T) {
|
||||
stateStore := state.NewStore(dbm.NewMemDB())
|
||||
blockStore := &mocks.BlockStore{}
|
||||
|
||||
_, _, err := state.Rollback(blockStore, stateStore)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "no state found")
|
||||
}
|
||||
|
||||
func TestRollbackNoBlocks(t *testing.T) {
|
||||
stateStore := state.NewStore(dbm.NewMemDB())
|
||||
blockStore := &mocks.BlockStore{}
|
||||
var (
|
||||
height int64 = 100
|
||||
appVersion uint64 = 10
|
||||
)
|
||||
|
||||
valSet, _ := types.RandValidatorSet(5, 10)
|
||||
|
||||
params := types.DefaultConsensusParams()
|
||||
params.Version.AppVersion = appVersion
|
||||
newParams := types.DefaultConsensusParams()
|
||||
newParams.Block.MaxBytes = 10000
|
||||
|
||||
initialState := state.State{
|
||||
Version: tmstate.Version{
|
||||
Consensus: tmversion.Consensus{
|
||||
Block: version.BlockProtocol,
|
||||
App: 10,
|
||||
},
|
||||
Software: version.TMCoreSemVer,
|
||||
},
|
||||
ChainID: "test-chain",
|
||||
InitialHeight: 10,
|
||||
LastBlockID: makeBlockIDRandom(),
|
||||
AppHash: tmhash.Sum([]byte("app_hash")),
|
||||
LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
|
||||
LastBlockHeight: height,
|
||||
LastValidators: valSet,
|
||||
Validators: valSet.CopyIncrementProposerPriority(1),
|
||||
NextValidators: valSet.CopyIncrementProposerPriority(2),
|
||||
LastHeightValidatorsChanged: height + 1,
|
||||
ConsensusParams: *params,
|
||||
LastHeightConsensusParamsChanged: height + 1,
|
||||
}
|
||||
require.NoError(t, stateStore.Save(initialState))
|
||||
blockStore.On("LoadBlockMeta", height).Return(nil)
|
||||
|
||||
_, _, err := state.Rollback(blockStore, stateStore)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "block at height 100 not found")
|
||||
}
|
||||
|
||||
func makeBlockIDRandom() types.BlockID {
|
||||
var (
|
||||
blockHash = make([]byte, tmhash.Size)
|
||||
partSetHash = make([]byte, tmhash.Size)
|
||||
)
|
||||
rand.Read(blockHash) //nolint: errcheck // ignore errcheck for read
|
||||
rand.Read(partSetHash) //nolint: errcheck // ignore errcheck for read
|
||||
return types.BlockID{
|
||||
Hash: blockHash,
|
||||
PartSetHeader: types.PartSetHeader{
|
||||
Total: 123,
|
||||
Hash: partSetHash,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
//------------------------------------------------------
|
||||
// blockstore
|
||||
|
||||
//go:generate mockery --case underscore --name BlockStore
|
||||
|
||||
// BlockStore defines the interface used by the ConsensusState.
|
||||
type BlockStore interface {
|
||||
Base() int64
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package statesync
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
tmsync "github.com/tendermint/tendermint/libs/sync"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
@@ -42,8 +40,6 @@ func (s *snapshot) Key() snapshotKey {
|
||||
|
||||
// snapshotPool discovers and aggregates snapshots across peers.
|
||||
type snapshotPool struct {
|
||||
stateProvider StateProvider
|
||||
|
||||
tmsync.Mutex
|
||||
snapshots map[snapshotKey]*snapshot
|
||||
snapshotPeers map[snapshotKey]map[p2p.ID]p2p.Peer
|
||||
@@ -60,9 +56,8 @@ type snapshotPool struct {
|
||||
}
|
||||
|
||||
// newSnapshotPool creates a new snapshot pool. The state source is used for
|
||||
func newSnapshotPool(stateProvider StateProvider) *snapshotPool {
|
||||
func newSnapshotPool() *snapshotPool {
|
||||
return &snapshotPool{
|
||||
stateProvider: stateProvider,
|
||||
snapshots: make(map[snapshotKey]*snapshot),
|
||||
snapshotPeers: make(map[snapshotKey]map[p2p.ID]p2p.Peer),
|
||||
formatIndex: make(map[uint32]map[snapshotKey]bool),
|
||||
@@ -78,14 +73,6 @@ func newSnapshotPool(stateProvider StateProvider) *snapshotPool {
|
||||
// returns true if this was a new, non-blacklisted snapshot. The snapshot height is verified using
|
||||
// the light client, and the expected app hash is set for the snapshot.
|
||||
func (p *snapshotPool) Add(peer p2p.Peer, snapshot *snapshot) (bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
appHash, err := p.stateProvider.AppHash(ctx, snapshot.Height)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
snapshot.trustedAppHash = appHash
|
||||
key := snapshot.Key()
|
||||
|
||||
p.Lock()
|
||||
|
||||
@@ -4,12 +4,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
p2pmocks "github.com/tendermint/tendermint/p2p/mocks"
|
||||
"github.com/tendermint/tendermint/statesync/mocks"
|
||||
)
|
||||
|
||||
func TestSnapshot_Key(t *testing.T) {
|
||||
@@ -41,14 +39,11 @@ func TestSnapshot_Key(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_Add(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, uint64(1)).Return([]byte("app_hash"), nil)
|
||||
|
||||
peer := &p2pmocks.Peer{}
|
||||
peer.On("ID").Return(p2p.ID("id"))
|
||||
|
||||
// Adding to the pool should work
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
added, err := pool.Add(peer, &snapshot{
|
||||
Height: 1,
|
||||
Format: 1,
|
||||
@@ -73,15 +68,10 @@ func TestSnapshotPool_Add(t *testing.T) {
|
||||
// The pool should have populated the snapshot with the trusted app hash
|
||||
snapshot := pool.Best()
|
||||
require.NotNil(t, snapshot)
|
||||
assert.Equal(t, []byte("app_hash"), snapshot.trustedAppHash)
|
||||
|
||||
stateProvider.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestSnapshotPool_GetPeer(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
|
||||
s := &snapshot{Height: 1, Format: 1, Chunks: 1, Hash: []byte{1}}
|
||||
peerA := &p2pmocks.Peer{}
|
||||
@@ -115,9 +105,7 @@ func TestSnapshotPool_GetPeer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_GetPeers(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
|
||||
s := &snapshot{Height: 1, Format: 1, Chunks: 1, Hash: []byte{1}}
|
||||
peerA := &p2pmocks.Peer{}
|
||||
@@ -139,9 +127,7 @@ func TestSnapshotPool_GetPeers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_Ranked_Best(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
|
||||
// snapshots in expected order (best to worst). Highest height wins, then highest format.
|
||||
// Snapshots with different chunk hashes are considered different, and the most peers is
|
||||
@@ -184,9 +170,7 @@ func TestSnapshotPool_Ranked_Best(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_Reject(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
peer := &p2pmocks.Peer{}
|
||||
peer.On("ID").Return(p2p.ID("id"))
|
||||
|
||||
@@ -214,9 +198,7 @@ func TestSnapshotPool_Reject(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_RejectFormat(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
peer := &p2pmocks.Peer{}
|
||||
peer.On("ID").Return(p2p.ID("id"))
|
||||
|
||||
@@ -245,9 +227,7 @@ func TestSnapshotPool_RejectFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_RejectPeer(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
|
||||
peerA := &p2pmocks.Peer{}
|
||||
peerA.On("ID").Return(p2p.ID("a"))
|
||||
@@ -287,9 +267,7 @@ func TestSnapshotPool_RejectPeer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSnapshotPool_RemovePeer(t *testing.T) {
|
||||
stateProvider := &mocks.StateProvider{}
|
||||
stateProvider.On("AppHash", mock.Anything, mock.Anything).Return([]byte("app_hash"), nil)
|
||||
pool := newSnapshotPool(stateProvider)
|
||||
pool := newSnapshotPool()
|
||||
|
||||
peerA := &p2pmocks.Peer{}
|
||||
peerA.On("ID").Return(p2p.ID("a"))
|
||||
|
||||
@@ -106,10 +106,6 @@ func (s *lightClientStateProvider) AppHash(ctx context.Context, height uint64) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = s.lc.VerifyLightBlockAtHeight(ctx, int64(height), time.Now())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return header.AppHash, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/tendermint/tendermint/config"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmsync "github.com/tendermint/tendermint/libs/sync"
|
||||
"github.com/tendermint/tendermint/light"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
@@ -78,7 +79,7 @@ func newSyncer(
|
||||
stateProvider: stateProvider,
|
||||
conn: conn,
|
||||
connQuery: connQuery,
|
||||
snapshots: newSnapshotPool(stateProvider),
|
||||
snapshots: newSnapshotPool(),
|
||||
tempDir: tempDir,
|
||||
chunkFetchers: cfg.ChunkFetchers,
|
||||
retryTimeout: cfg.ChunkRequestTimeout,
|
||||
@@ -247,30 +248,51 @@ func (s *syncer) Sync(snapshot *snapshot, chunks *chunkQueue) (sm.State, *types.
|
||||
s.mtx.Unlock()
|
||||
}()
|
||||
|
||||
hctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
appHash, err := s.stateProvider.AppHash(hctx, snapshot.Height)
|
||||
if err != nil {
|
||||
s.logger.Info("failed to fetch and verify app hash", "err", err)
|
||||
if err == light.ErrNoWitnesses {
|
||||
return sm.State{}, nil, err
|
||||
}
|
||||
return sm.State{}, nil, errRejectSnapshot
|
||||
}
|
||||
snapshot.trustedAppHash = appHash
|
||||
|
||||
// Offer snapshot to ABCI app.
|
||||
err := s.offerSnapshot(snapshot)
|
||||
err = s.offerSnapshot(snapshot)
|
||||
if err != nil {
|
||||
return sm.State{}, nil, err
|
||||
}
|
||||
|
||||
// Spawn chunk fetchers. They will terminate when the chunk queue is closed or context cancelled.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
fetchCtx, cancel := context.WithCancel(context.TODO())
|
||||
defer cancel()
|
||||
for i := int32(0); i < s.chunkFetchers; i++ {
|
||||
go s.fetchChunks(ctx, snapshot, chunks)
|
||||
go s.fetchChunks(fetchCtx, snapshot, chunks)
|
||||
}
|
||||
|
||||
pctx, pcancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
pctx, pcancel := context.WithTimeout(context.TODO(), 30*time.Second)
|
||||
defer pcancel()
|
||||
|
||||
// Optimistically build new state, so we don't discover any light client failures at the end.
|
||||
state, err := s.stateProvider.State(pctx, snapshot.Height)
|
||||
if err != nil {
|
||||
return sm.State{}, nil, fmt.Errorf("failed to build new state: %w", err)
|
||||
s.logger.Info("failed to fetch and verify tendermint state", "err", err)
|
||||
if err == light.ErrNoWitnesses {
|
||||
return sm.State{}, nil, err
|
||||
}
|
||||
return sm.State{}, nil, errRejectSnapshot
|
||||
}
|
||||
commit, err := s.stateProvider.Commit(pctx, snapshot.Height)
|
||||
if err != nil {
|
||||
return sm.State{}, nil, fmt.Errorf("failed to fetch commit: %w", err)
|
||||
s.logger.Info("failed to fetch and verify commit", "err", err)
|
||||
if err == light.ErrNoWitnesses {
|
||||
return sm.State{}, nil, err
|
||||
}
|
||||
return sm.State{}, nil, errRejectSnapshot
|
||||
}
|
||||
|
||||
// Restore snapshot
|
||||
|
||||
@@ -6,8 +6,8 @@ docker:
|
||||
# We need to build support for database backends into the app in
|
||||
# order to build a binary with a Tendermint node in it (for built-in
|
||||
# ABCI testing).
|
||||
app:
|
||||
go build -o build/app -tags badgerdb,boltdb,cleveldb,rocksdb ./app
|
||||
node:
|
||||
go build -o build/node -tags badgerdb,boltdb,cleveldb,rocksdb ./node
|
||||
|
||||
# To be used primarily by the e2e docker instance. If you want to produce this binary
|
||||
# elsewhere, then run go build in the maverick directory.
|
||||
@@ -20,4 +20,4 @@ generator:
|
||||
runner:
|
||||
go build -o build/runner ./runner
|
||||
|
||||
.PHONY: all app docker generator maverick runner
|
||||
.PHONY: all node docker generator maverick runner
|
||||
|
||||
@@ -122,10 +122,42 @@ Docker does not enable IPv6 by default. To do so, enter the following in
|
||||
}
|
||||
```
|
||||
|
||||
## Benchmarking testnets
|
||||
## Benchmarking Testnets
|
||||
|
||||
It is also possible to run a simple benchmark on a testnet. This is done through the `benchmark` command. This manages the entire process: setting up the environment, starting the test net, waiting for a considerable amount of blocks to be used (currently 100), and then returning the following metrics from the sample of the blockchain:
|
||||
|
||||
- Average time to produce a block
|
||||
- Standard deviation of producing a block
|
||||
- Minimum and maximum time to produce a block
|
||||
|
||||
## Running Individual Nodes
|
||||
|
||||
The E2E test harness is designed to run several nodes of varying configurations within docker. It is also possible to run a single node in the case of running larger, geographically-dispersed testnets. To run a single node you can either run:
|
||||
|
||||
**Built-in**
|
||||
|
||||
```bash
|
||||
make node
|
||||
tendermint init validator
|
||||
TMHOME=$HOME/.tendermint ./build/node ./node/built-in.toml
|
||||
```
|
||||
|
||||
To make things simpler the e2e application can also be run in the tendermint binary
|
||||
by running
|
||||
|
||||
```bash
|
||||
tendermint start --proxy-app e2e
|
||||
```
|
||||
|
||||
However this won't offer the same level of configurability of the application.
|
||||
|
||||
**Socket**
|
||||
|
||||
```bash
|
||||
make node
|
||||
tendermint init validator
|
||||
tendermint start
|
||||
./build/node ./node.socket.toml
|
||||
```
|
||||
|
||||
Check `node/config.go` to see how the settings of the test application can be tweaked.
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -28,6 +28,55 @@ type Application struct {
|
||||
restoreChunks [][]byte
|
||||
}
|
||||
|
||||
// Config allows for the setting of high level parameters for running the e2e Application
|
||||
// KeyType and ValidatorUpdates must be the same for all nodes running the same application.
|
||||
type Config struct {
|
||||
// The directory with which state.json will be persisted in. Usually $HOME/.tendermint/data
|
||||
Dir string `toml:"dir"`
|
||||
|
||||
// SnapshotInterval specifies the height interval at which the application
|
||||
// will take state sync snapshots. Defaults to 0 (disabled).
|
||||
SnapshotInterval uint64 `toml:"snapshot_interval"`
|
||||
|
||||
// RetainBlocks specifies the number of recent blocks to retain. Defaults to
|
||||
// 0, which retains all blocks. Must be greater that PersistInterval,
|
||||
// SnapshotInterval and EvidenceAgeHeight.
|
||||
RetainBlocks uint64 `toml:"retain_blocks"`
|
||||
|
||||
// KeyType sets the curve that will be used by validators.
|
||||
// Options are ed25519 & secp256k1
|
||||
KeyType string `toml:"key_type"`
|
||||
|
||||
// PersistInterval specifies the height interval at which the application
|
||||
// will persist state to disk. Defaults to 1 (every height), setting this to
|
||||
// 0 disables state persistence.
|
||||
PersistInterval uint64 `toml:"persist_interval"`
|
||||
|
||||
// ValidatorUpdates is a map of heights to validator names and their power,
|
||||
// and will be returned by the ABCI application. For example, the following
|
||||
// changes the power of validator01 and validator02 at height 1000:
|
||||
//
|
||||
// [validator_update.1000]
|
||||
// validator01 = 20
|
||||
// validator02 = 10
|
||||
//
|
||||
// Specifying height 0 returns the validator update during InitChain. The
|
||||
// application returns the validator updates as-is, i.e. removing a
|
||||
// validator must be done by returning it with power 0, and any validators
|
||||
// not specified are not changed.
|
||||
//
|
||||
// height <-> pubkey <-> voting power
|
||||
ValidatorUpdates map[string]map[string]uint8 `toml:"validator_update"`
|
||||
}
|
||||
|
||||
func DefaultConfig(dir string) *Config {
|
||||
return &Config{
|
||||
PersistInterval: 1,
|
||||
SnapshotInterval: 100,
|
||||
Dir: dir,
|
||||
}
|
||||
}
|
||||
|
||||
// NewApplication creates the application.
|
||||
func NewApplication(cfg *Config) (*Application, error) {
|
||||
state, err := NewState(filepath.Join(cfg.Dir, "state.json"), cfg.PersistInterval)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// nolint: gosec
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//nolint: gosec
|
||||
package main
|
||||
package app
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
@@ -19,7 +19,7 @@ COPY . .
|
||||
RUN make build && cp build/tendermint /usr/bin/tendermint
|
||||
COPY test/e2e/docker/entrypoint* /usr/bin/
|
||||
RUN cd test/e2e && make maverick && cp build/maverick /usr/bin/maverick
|
||||
RUN cd test/e2e && make app && cp build/app /usr/bin/app
|
||||
RUN cd test/e2e && make node && cp build/node /usr/bin/app
|
||||
|
||||
# Set up runtime directory. We don't use a separate runtime image since we need
|
||||
# e.g. leveldb and rocksdb which are already installed in the build image.
|
||||
|
||||
@@ -15,7 +15,6 @@ var (
|
||||
// separate testnet for each combination (Cartesian product) of options.
|
||||
testnetCombinations = map[string][]interface{}{
|
||||
"topology": {"single", "quad", "large"},
|
||||
"ipv6": {false, true},
|
||||
"initialHeight": {0, 1000},
|
||||
"initialState": {
|
||||
map[string]string{},
|
||||
@@ -26,11 +25,12 @@ var (
|
||||
|
||||
// The following specify randomly chosen values for testnet nodes.
|
||||
nodeDatabases = uniformChoice{"goleveldb", "cleveldb", "rocksdb", "boltdb", "badgerdb"}
|
||||
ipv6 = uniformChoice{false, true}
|
||||
// FIXME: grpc disabled due to https://github.com/tendermint/tendermint/issues/5439
|
||||
nodeABCIProtocols = uniformChoice{"unix", "tcp", "builtin"} // "grpc"
|
||||
nodePrivvalProtocols = uniformChoice{"file", "unix", "tcp"}
|
||||
// FIXME: v2 disabled due to flake
|
||||
nodeFastSyncs = uniformChoice{"", "v0"} // "v2"
|
||||
nodeFastSyncs = uniformChoice{"v0"} // "v2"
|
||||
nodeStateSyncs = uniformChoice{false, true}
|
||||
nodePersistIntervals = uniformChoice{0, 1, 5}
|
||||
nodeSnapshotIntervals = uniformChoice{0, 3}
|
||||
@@ -66,7 +66,8 @@ func Generate(r *rand.Rand) ([]e2e.Manifest, error) {
|
||||
// generateTestnet generates a single testnet with the given options.
|
||||
func generateTestnet(r *rand.Rand, opt map[string]interface{}) (e2e.Manifest, error) {
|
||||
manifest := e2e.Manifest{
|
||||
IPv6: opt["ipv6"].(bool),
|
||||
IPv6: ipv6.Choose(r).(bool),
|
||||
ABCIProtocol: nodeABCIProtocols.Choose(r).(string),
|
||||
InitialHeight: int64(opt["initialHeight"].(int)),
|
||||
InitialState: opt["initialState"].(map[string]string),
|
||||
Validators: &map[string]int64{},
|
||||
@@ -207,7 +208,6 @@ func generateNode(
|
||||
Mode: string(mode),
|
||||
StartAt: startAt,
|
||||
Database: nodeDatabases.Choose(r).(string),
|
||||
ABCIProtocol: nodeABCIProtocols.Choose(r).(string),
|
||||
PrivvalProtocol: nodePrivvalProtocols.Choose(r).(string),
|
||||
FastSync: nodeFastSyncs.Choose(r).(string),
|
||||
StateSync: nodeStateSyncs.Choose(r).(bool) && startAt > 0,
|
||||
@@ -264,7 +264,6 @@ func generateLightNode(r *rand.Rand, startAt int64, providers []string) *e2e.Man
|
||||
Mode: string(e2e.ModeLight),
|
||||
StartAt: startAt,
|
||||
Database: nodeDatabases.Choose(r).(string),
|
||||
ABCIProtocol: "builtin",
|
||||
PersistInterval: ptrUint64(0),
|
||||
PersistentPeers: providers,
|
||||
}
|
||||
|
||||
4
test/e2e/node/built-in.toml
Normal file
4
test/e2e/node/built-in.toml
Normal file
@@ -0,0 +1,4 @@
|
||||
snapshot_interval = 100
|
||||
persist_interval = 1
|
||||
chain_id = "test-chain"
|
||||
protocol = "builtin"
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"github.com/tendermint/tendermint/test/e2e/app"
|
||||
)
|
||||
|
||||
// Config is the application configuration.
|
||||
@@ -26,6 +28,18 @@ type Config struct {
|
||||
KeyType string `toml:"key_type"`
|
||||
}
|
||||
|
||||
// App extracts out the application specific configuration parameters
|
||||
func (cfg *Config) App() *app.Config {
|
||||
return &app.Config{
|
||||
Dir: cfg.Dir,
|
||||
SnapshotInterval: cfg.SnapshotInterval,
|
||||
RetainBlocks: cfg.RetainBlocks,
|
||||
KeyType: cfg.KeyType,
|
||||
ValidatorUpdates: cfg.ValidatorUpdates,
|
||||
PersistInterval: cfg.PersistInterval,
|
||||
}
|
||||
}
|
||||
|
||||
// LoadConfig loads the configuration from disk.
|
||||
func LoadConfig(file string) (*Config, error) {
|
||||
cfg := &Config{
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
rpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
|
||||
"github.com/tendermint/tendermint/test/e2e/app"
|
||||
e2e "github.com/tendermint/tendermint/test/e2e/pkg"
|
||||
mcs "github.com/tendermint/tendermint/test/maverick/consensus"
|
||||
maverick "github.com/tendermint/tendermint/test/maverick/node"
|
||||
@@ -98,7 +99,7 @@ func run(configFile string) error {
|
||||
|
||||
// startApp starts the application server, listening for connections from Tendermint.
|
||||
func startApp(cfg *Config) error {
|
||||
app, err := NewApplication(cfg)
|
||||
app, err := app.NewApplication(cfg.App())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -119,7 +120,7 @@ func startApp(cfg *Config) error {
|
||||
//
|
||||
// FIXME There is no way to simply load the configuration from a file, so we need to pull in Viper.
|
||||
func startNode(cfg *Config) error {
|
||||
app, err := NewApplication(cfg)
|
||||
app, err := app.NewApplication(cfg.App())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -205,7 +206,7 @@ func startLightClient(cfg *Config) error {
|
||||
// startMaverick starts a Maverick node that runs the application directly. It assumes the Tendermint
|
||||
// configuration is in $TMHOME/config/tendermint.toml.
|
||||
func startMaverick(cfg *Config) error {
|
||||
app, err := NewApplication(cfg)
|
||||
app, err := app.NewApplication(cfg.App())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
5
test/e2e/node/socket.toml
Normal file
5
test/e2e/node/socket.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
snapshot_interval = 100
|
||||
persist_interval = 1
|
||||
chain_id = "test-chain"
|
||||
protocol = "socket"
|
||||
listen = "tcp://127.0.0.1:26658"
|
||||
@@ -50,6 +50,12 @@ type Manifest struct {
|
||||
// KeyType sets the curve that will be used by validators.
|
||||
// Options are ed25519 & secp256k1
|
||||
KeyType string `toml:"key_type"`
|
||||
|
||||
// ABCIProtocol specifies the protocol used to communicate with the ABCI
|
||||
// application: "unix", "tcp", "grpc", or "builtin". Defaults to builtin.
|
||||
// builtin will build a complete Tendermint node into the application and
|
||||
// launch it instead of launching a separate Tendermint process.
|
||||
ABCIProtocol string `toml:"abci_protocol"`
|
||||
}
|
||||
|
||||
// ManifestNode represents a node in a testnet manifest.
|
||||
@@ -72,12 +78,6 @@ type ManifestNode struct {
|
||||
// "rocksdb", "boltdb", or "badgerdb". Defaults to goleveldb.
|
||||
Database string `toml:"database"`
|
||||
|
||||
// ABCIProtocol specifies the protocol used to communicate with the ABCI
|
||||
// application: "unix", "tcp", "grpc", or "builtin". Defaults to unix.
|
||||
// builtin will build a complete Tendermint node into the application and
|
||||
// launch it instead of launching a separate Tendermint process.
|
||||
ABCIProtocol string `toml:"abci_protocol"`
|
||||
|
||||
// PrivvalProtocol specifies the protocol used to sign consensus messages:
|
||||
// "file", "unix", or "tcp". Defaults to "file". For unix and tcp, the ABCI
|
||||
// application will launch a remote signer client in a separate goroutine.
|
||||
|
||||
@@ -60,6 +60,7 @@ type Testnet struct {
|
||||
ValidatorUpdates map[int64]map[*Node]int64
|
||||
Nodes []*Node
|
||||
KeyType string
|
||||
ABCIProtocol string
|
||||
}
|
||||
|
||||
// Node represents a Tendermint node in a testnet.
|
||||
@@ -122,10 +123,17 @@ func LoadTestnet(file string) (*Testnet, error) {
|
||||
Validators: map[*Node]int64{},
|
||||
ValidatorUpdates: map[int64]map[*Node]int64{},
|
||||
Nodes: []*Node{},
|
||||
ABCIProtocol: manifest.ABCIProtocol,
|
||||
}
|
||||
if len(manifest.KeyType) != 0 {
|
||||
testnet.KeyType = manifest.KeyType
|
||||
}
|
||||
if manifest.InitialHeight > 0 {
|
||||
testnet.InitialHeight = manifest.InitialHeight
|
||||
}
|
||||
if testnet.ABCIProtocol == "" {
|
||||
testnet.ABCIProtocol = string(ProtocolBuiltin)
|
||||
}
|
||||
|
||||
// Set up nodes, in alphabetical order (IPs and ports get same order).
|
||||
nodeNames := []string{}
|
||||
@@ -145,7 +153,7 @@ func LoadTestnet(file string) (*Testnet, error) {
|
||||
ProxyPort: proxyPortGen.Next(),
|
||||
Mode: ModeValidator,
|
||||
Database: "goleveldb",
|
||||
ABCIProtocol: ProtocolBuiltin,
|
||||
ABCIProtocol: Protocol(testnet.ABCIProtocol),
|
||||
PrivvalProtocol: ProtocolFile,
|
||||
StartAt: nodeManifest.StartAt,
|
||||
FastSync: nodeManifest.FastSync,
|
||||
@@ -162,12 +170,12 @@ func LoadTestnet(file string) (*Testnet, error) {
|
||||
if nodeManifest.Mode != "" {
|
||||
node.Mode = Mode(nodeManifest.Mode)
|
||||
}
|
||||
if node.Mode == ModeLight {
|
||||
node.ABCIProtocol = ProtocolBuiltin
|
||||
}
|
||||
if nodeManifest.Database != "" {
|
||||
node.Database = nodeManifest.Database
|
||||
}
|
||||
if nodeManifest.ABCIProtocol != "" {
|
||||
node.ABCIProtocol = Protocol(nodeManifest.ABCIProtocol)
|
||||
}
|
||||
if nodeManifest.PrivvalProtocol != "" {
|
||||
node.PrivvalProtocol = Protocol(nodeManifest.PrivvalProtocol)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
)
|
||||
|
||||
func Start(testnet *e2e.Testnet) error {
|
||||
if len(testnet.Nodes) == 0 {
|
||||
return fmt.Errorf("no nodes in testnet")
|
||||
}
|
||||
|
||||
// Nodes are already sorted by name. Sort them by name then startAt,
|
||||
// which gives the overall order startAt, mode, name.
|
||||
@@ -25,12 +28,11 @@ func Start(testnet *e2e.Testnet) error {
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
sort.SliceStable(nodeQueue, func(i, j int) bool {
|
||||
return nodeQueue[i].StartAt < nodeQueue[j].StartAt
|
||||
})
|
||||
if len(nodeQueue) == 0 {
|
||||
return fmt.Errorf("no nodes in testnet")
|
||||
}
|
||||
|
||||
if nodeQueue[0].StartAt > 0 {
|
||||
return fmt.Errorf("no initial nodes in testnet")
|
||||
}
|
||||
@@ -49,9 +51,15 @@ func Start(testnet *e2e.Testnet) error {
|
||||
logger.Info(fmt.Sprintf("Node %v up on http://127.0.0.1:%v", node.Name, node.ProxyPort))
|
||||
}
|
||||
|
||||
networkHeight := testnet.InitialHeight
|
||||
|
||||
// Wait for initial height
|
||||
logger.Info(fmt.Sprintf("Waiting for initial height %v...", testnet.InitialHeight))
|
||||
block, blockID, err := waitForHeight(testnet, testnet.InitialHeight)
|
||||
logger.Info("Waiting for initial height",
|
||||
"height", networkHeight,
|
||||
"nodes", len(testnet.Nodes)-len(nodeQueue),
|
||||
"pending", len(nodeQueue))
|
||||
|
||||
block, blockID, err := waitForHeight(testnet, networkHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -66,12 +74,28 @@ func Start(testnet *e2e.Testnet) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Start up remaining nodes
|
||||
for _, node := range nodeQueue {
|
||||
logger.Info(fmt.Sprintf("Starting node %v at height %v...", node.Name, node.StartAt))
|
||||
if _, _, err := waitForHeight(testnet, node.StartAt); err != nil {
|
||||
return err
|
||||
if node.StartAt > networkHeight {
|
||||
// if we're starting a node that's ahead of
|
||||
// the last known height of the network, then
|
||||
// we should make sure that the rest of the
|
||||
// network has reached at least the height
|
||||
// that this node will start at before we
|
||||
// start the node.
|
||||
|
||||
networkHeight = node.StartAt
|
||||
|
||||
logger.Info("Waiting for network to advance before starting catch up node",
|
||||
"node", node.Name,
|
||||
"height", networkHeight)
|
||||
|
||||
if _, _, err := waitForHeight(testnet, networkHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Starting catch up node", "node", node.Name, "height", node.StartAt)
|
||||
|
||||
if err := execCompose(testnet.Dir, "up", "-d", node.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,9 +17,6 @@ import (
|
||||
// Tests that any initial state given in genesis has made it into the app.
|
||||
func TestApp_InitialState(t *testing.T) {
|
||||
testNode(t, func(t *testing.T, node e2e.Node) {
|
||||
if node.Stateless() {
|
||||
return
|
||||
}
|
||||
if len(node.Testnet.InitialState) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -39,12 +36,6 @@ func TestApp_InitialState(t *testing.T) {
|
||||
// block and the node sync status.
|
||||
func TestApp_Hash(t *testing.T) {
|
||||
testNode(t, func(t *testing.T, node e2e.Node) {
|
||||
// disables tests for light clients
|
||||
// see https://github.com/tendermint/tendermint/issues/6671
|
||||
if node.Mode == e2e.ModeSeed || node.Mode == e2e.ModeLight {
|
||||
return
|
||||
}
|
||||
|
||||
client, err := node.Client()
|
||||
require.NoError(t, err)
|
||||
info, err := client.ABCIInfo(ctx)
|
||||
@@ -66,12 +57,6 @@ func TestApp_Hash(t *testing.T) {
|
||||
// Tests that we can set a value and retrieve it.
|
||||
func TestApp_Tx(t *testing.T) {
|
||||
testNode(t, func(t *testing.T, node e2e.Node) {
|
||||
// disables tests for light clients
|
||||
// see https://github.com/tendermint/tendermint/issues/6671
|
||||
if node.Mode == e2e.ModeSeed || node.Mode == e2e.ModeLight {
|
||||
return
|
||||
}
|
||||
|
||||
client, err := node.Client()
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -50,6 +50,10 @@ func testNode(t *testing.T, testFunc func(*testing.T, e2e.Node)) {
|
||||
}
|
||||
|
||||
for _, node := range nodes {
|
||||
if node.Stateless() {
|
||||
continue
|
||||
}
|
||||
|
||||
node := *node
|
||||
t.Run(node.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
1
tests.mk
1
tests.mk
@@ -37,6 +37,7 @@ test_integrations:
|
||||
make build_docker_test_image
|
||||
make tools
|
||||
make install
|
||||
make install_abci
|
||||
make test_cover
|
||||
make test_apps
|
||||
make test_abci_apps
|
||||
|
||||
@@ -7,7 +7,7 @@ var (
|
||||
const (
|
||||
// TMVersionDefault is the used as the fallback version of Tendermint Core
|
||||
// when not using git describe. It is formatted with semantic versioning.
|
||||
TMVersionDefault = "0.34.11"
|
||||
TMVersionDefault = "0.34.14"
|
||||
// ABCISemVer is the semantic version of the ABCI library
|
||||
ABCISemVer = "0.17.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user