diff --git a/.changelog/unreleased/bug-fixes/423-forwardport-default-kvindexer-behaviour.md b/.changelog/unreleased/bug-fixes/423-forwardport-default-kvindexer-behaviour.md new file mode 100644 index 00000000000..0563a981af6 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/423-forwardport-default-kvindexer-behaviour.md @@ -0,0 +1,2 @@ +- `[kvindexer]` Forward porting the fixes done to the kvindexer in 0.37 in PR \#77 + ([\#423](https://github.com/cometbft/cometbft/pull/423)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/496-error-on-applyblock-should-panic.md b/.changelog/unreleased/bug-fixes/496-error-on-applyblock-should-panic.md new file mode 100644 index 00000000000..55e9c874f8c --- /dev/null +++ b/.changelog/unreleased/bug-fixes/496-error-on-applyblock-should-panic.md @@ -0,0 +1,2 @@ +- `[consensus]` Unexpected error conditions in `ApplyBlock` are non-recoverable, so ignoring the error and carrying on is a bug. We replaced a `return` that disregarded the error by a `panic`. + ([\#496](https://github.com/cometbft/cometbft/pull/496)) \ No newline at end of file diff --git a/.changelog/unreleased/bug-fixes/524-rename-peerstate-tojson.md b/.changelog/unreleased/bug-fixes/524-rename-peerstate-tojson.md new file mode 100644 index 00000000000..b9a43b3ce4e --- /dev/null +++ b/.changelog/unreleased/bug-fixes/524-rename-peerstate-tojson.md @@ -0,0 +1,2 @@ +- `[consensus]` Rename `(*PeerState).ToJSON` to `MarshalJSON` to fix a logging data race + ([\#524](https://github.com/cometbft/cometbft/pull/524)) diff --git a/.changelog/unreleased/improvements/543-metrics-for-blocksync.md b/.changelog/unreleased/improvements/543-metrics-for-blocksync.md new file mode 100644 index 00000000000..824e20df9c1 --- /dev/null +++ b/.changelog/unreleased/improvements/543-metrics-for-blocksync.md @@ -0,0 +1,2 @@ +- `[blocksync]` Generate new metrics during BlockSync + ([\#543](https://github.com/cometbft/cometbft/pull/543)) \ No newline at end of file diff --git a/.changelog/v0.34.27/breaking-changes/152-rename-binary-docker.md b/.changelog/v0.34.27/breaking-changes/152-rename-binary-docker.md new file mode 100644 index 00000000000..3870f96f927 --- /dev/null +++ b/.changelog/v0.34.27/breaking-changes/152-rename-binary-docker.md @@ -0,0 +1,2 @@ +- Rename binary to `cometbft` and Docker image to `cometbft/cometbft` + ([\#152](https://github.com/cometbft/cometbft/pull/152)) diff --git a/.changelog/v0.34.27/breaking-changes/211-deprecate-tmhome.md b/.changelog/v0.34.27/breaking-changes/211-deprecate-tmhome.md new file mode 100644 index 00000000000..d2bded0f279 --- /dev/null +++ b/.changelog/v0.34.27/breaking-changes/211-deprecate-tmhome.md @@ -0,0 +1,3 @@ +- The `TMHOME` environment variable was renamed to `CMTHOME`, and all + environment variables starting with `TM_` are instead prefixed with `CMT_` + ([\#211](https://github.com/cometbft/cometbft/issues/211)) diff --git a/.changelog/v0.34.27/breaking-changes/360-update-to-go-119.md b/.changelog/v0.34.27/breaking-changes/360-update-to-go-119.md new file mode 100644 index 00000000000..97fafda93bb --- /dev/null +++ b/.changelog/v0.34.27/breaking-changes/360-update-to-go-119.md @@ -0,0 +1,2 @@ +- Use Go 1.19 to build CometBFT, since Go 1.18 has reached end-of-life. + ([\#360](https://github.com/cometbft/cometbft/issues/360)) diff --git a/.changelog/v0.34.27/bug-fixes/383-txindexer-fix-slash-parsing.md b/.changelog/v0.34.27/bug-fixes/383-txindexer-fix-slash-parsing.md new file mode 100644 index 00000000000..c08824da9d7 --- /dev/null +++ b/.changelog/v0.34.27/bug-fixes/383-txindexer-fix-slash-parsing.md @@ -0,0 +1,3 @@ +- `[state/kvindexer]` Resolved crashes when event values contained slashes, + introduced after adding event sequences. + (\#[383](https://github.com/cometbft/cometbft/pull/383): @jmalicevic) diff --git a/.changelog/v0.34.27/bug-fixes/386-quick-fix-needproofblock.md b/.changelog/v0.34.27/bug-fixes/386-quick-fix-needproofblock.md new file mode 100644 index 00000000000..d3d2f5b7387 --- /dev/null +++ b/.changelog/v0.34.27/bug-fixes/386-quick-fix-needproofblock.md @@ -0,0 +1,6 @@ +- `[consensus]` Short-term fix for the case when `needProofBlock` cannot find + previous block meta by defaulting to the creation of a new proof block. + ([\#386](https://github.com/cometbft/cometbft/pull/386): @adizere) + - Special thanks to the [Vega.xyz](https://vega.xyz/) team, and in particular + to Zohar (@ze97286), for reporting the problem and working with us to get to + a fix. diff --git a/.changelog/v0.34.27/bug-fixes/4-busy-loop-send-block-part.md b/.changelog/v0.34.27/bug-fixes/4-busy-loop-send-block-part.md new file mode 100644 index 00000000000..414ec44cb10 --- /dev/null +++ b/.changelog/v0.34.27/bug-fixes/4-busy-loop-send-block-part.md @@ -0,0 +1,3 @@ +- `[consensus]` Fixed a busy loop that happened when sending of a block part + failed by sleeping in case of error. + ([\#4](https://github.com/informalsystems/tendermint/pull/4)) diff --git a/.changelog/v0.34.27/bug-fixes/9936-p2p-fix-envelope-sending.md b/.changelog/v0.34.27/bug-fixes/9936-p2p-fix-envelope-sending.md new file mode 100644 index 00000000000..fd38b79b9f7 --- /dev/null +++ b/.changelog/v0.34.27/bug-fixes/9936-p2p-fix-envelope-sending.md @@ -0,0 +1,5 @@ +- `[p2p]` Correctly use non-blocking `TrySendEnvelope` method when attempting to + send messages, as opposed to the blocking `SendEnvelope` method. It is unclear + whether this has a meaningful impact on P2P performance, but this patch does + correct the underlying behaviour to what it should be + ([tendermint/tendermint\#9936](https://github.com/tendermint/tendermint/pull/9936)) diff --git a/.changelog/v0.34.27/dependencies/160-tmdb-to-cometbftdb.md b/.changelog/v0.34.27/dependencies/160-tmdb-to-cometbftdb.md new file mode 100644 index 00000000000..e4c1351312c --- /dev/null +++ b/.changelog/v0.34.27/dependencies/160-tmdb-to-cometbftdb.md @@ -0,0 +1,3 @@ +- Replace [tm-db](https://github.com/tendermint/tm-db) with + [cometbft-db](https://github.com/cometbft/cometbft-db) + ([\#160](https://github.com/cometbft/cometbft/pull/160)) \ No newline at end of file diff --git a/.changelog/v0.34.27/dependencies/165-bump-tmloadtest.md b/.changelog/v0.34.27/dependencies/165-bump-tmloadtest.md new file mode 100644 index 00000000000..175163ac004 --- /dev/null +++ b/.changelog/v0.34.27/dependencies/165-bump-tmloadtest.md @@ -0,0 +1,2 @@ +- Bump tm-load-test to v1.3.0 to remove implicit dependency on Tendermint Core + ([\#165](https://github.com/cometbft/cometbft/pull/165)) \ No newline at end of file diff --git a/.changelog/v0.34.27/dependencies/9787-btcec-dep-update.md b/.changelog/v0.34.27/dependencies/9787-btcec-dep-update.md new file mode 100644 index 00000000000..d155748e0cb --- /dev/null +++ b/.changelog/v0.34.27/dependencies/9787-btcec-dep-update.md @@ -0,0 +1,3 @@ +- `[crypto]` Update to use btcec v2 and the latest btcutil + ([tendermint/tendermint\#9787](https://github.com/tendermint/tendermint/pull/9787): + @wcsiu) diff --git a/.changelog/v0.34.27/features/9759-kvindexer-match-event.md b/.changelog/v0.34.27/features/9759-kvindexer-match-event.md new file mode 100644 index 00000000000..281f6cd1fb8 --- /dev/null +++ b/.changelog/v0.34.27/features/9759-kvindexer-match-event.md @@ -0,0 +1,3 @@ +- `[rpc]` Add `match_event` query parameter to indicate to the RPC that it + should match events _within_ attributes, not only within a height + ([tendermint/tendermint\#9759](https://github.com/tendermint/tendermint/pull/9759)) diff --git a/.changelog/v0.34.27/improvements/136-remove-tm-signer-harness.md b/.changelog/v0.34.27/improvements/136-remove-tm-signer-harness.md new file mode 100644 index 00000000000..6eb6c2158c2 --- /dev/null +++ b/.changelog/v0.34.27/improvements/136-remove-tm-signer-harness.md @@ -0,0 +1,2 @@ +- `[tools/tm-signer-harness]` Remove the folder as it is unused + ([\#136](https://github.com/cometbft/cometbft/issues/136)) \ No newline at end of file diff --git a/.changelog/v0.34.27/improvements/204-version-commit-hash.md b/.changelog/v0.34.27/improvements/204-version-commit-hash.md new file mode 100644 index 00000000000..675a1a2924b --- /dev/null +++ b/.changelog/v0.34.27/improvements/204-version-commit-hash.md @@ -0,0 +1,2 @@ +- Append the commit hash to the version of CometBFT being built + ([\#204](https://github.com/cometbft/cometbft/pull/204)) \ No newline at end of file diff --git a/.changelog/v0.34.27/improvements/314-prio-mempool-badtxlog.md b/.changelog/v0.34.27/improvements/314-prio-mempool-badtxlog.md new file mode 100644 index 00000000000..ba4ac031e20 --- /dev/null +++ b/.changelog/v0.34.27/improvements/314-prio-mempool-badtxlog.md @@ -0,0 +1,3 @@ +- `[mempool/v1]` Suppress "rejected bad transaction" in priority mempool logs by + reducing log level from info to debug + ([\#314](https://github.com/cometbft/cometbft/pull/314): @JayT106) diff --git a/.changelog/v0.34.27/improvements/56-rpc-cache-rpc-responses.md b/.changelog/v0.34.27/improvements/56-rpc-cache-rpc-responses.md new file mode 100644 index 00000000000..344b3df93b9 --- /dev/null +++ b/.changelog/v0.34.27/improvements/56-rpc-cache-rpc-responses.md @@ -0,0 +1,2 @@ +- `[e2e]` Add functionality for uncoordinated (minor) upgrades + ([\#56](https://github.com/tendermint/tendermint/pull/56)) \ No newline at end of file diff --git a/.changelog/v0.34.27/improvements/9733-consensus-metrics.md b/.changelog/v0.34.27/improvements/9733-consensus-metrics.md new file mode 100644 index 00000000000..77d8c743ec7 --- /dev/null +++ b/.changelog/v0.34.27/improvements/9733-consensus-metrics.md @@ -0,0 +1,4 @@ +- `[consensus]` Add `consensus_block_gossip_parts_received` and + `consensus_step_duration_seconds` metrics in order to aid in investigating the + impact of database compaction on consensus performance + ([tendermint/tendermint\#9733](https://github.com/tendermint/tendermint/pull/9733)) diff --git a/.changelog/v0.34.27/improvements/9759-kvindexer-match-event.md b/.changelog/v0.34.27/improvements/9759-kvindexer-match-event.md new file mode 100644 index 00000000000..8b5757cb8ec --- /dev/null +++ b/.changelog/v0.34.27/improvements/9759-kvindexer-match-event.md @@ -0,0 +1,3 @@ +- `[state/kvindexer]` Add `match.event` keyword to support condition evaluation + based on the event the attributes belong to + ([tendermint/tendermint\#9759](https://github.com/tendermint/tendermint/pull/9759)) diff --git a/.changelog/v0.34.27/improvements/9764-p2p-fix-logspam.md b/.changelog/v0.34.27/improvements/9764-p2p-fix-logspam.md new file mode 100644 index 00000000000..78fa6844fee --- /dev/null +++ b/.changelog/v0.34.27/improvements/9764-p2p-fix-logspam.md @@ -0,0 +1,4 @@ +- `[p2p]` Reduce log spam through reducing log level of "Dialing peer" and + "Added peer" messages from info to debug + ([tendermint/tendermint\#9764](https://github.com/tendermint/tendermint/pull/9764): + @faddat) diff --git a/.changelog/v0.34.27/improvements/9776-consensus-vote-bandwidth.md b/.changelog/v0.34.27/improvements/9776-consensus-vote-bandwidth.md new file mode 100644 index 00000000000..2bfdd05acf8 --- /dev/null +++ b/.changelog/v0.34.27/improvements/9776-consensus-vote-bandwidth.md @@ -0,0 +1,3 @@ +- `[consensus]` Reduce bandwidth consumption of consensus votes by roughly 50% + through fixing a small logic bug + ([tendermint/tendermint\#9776](https://github.com/tendermint/tendermint/pull/9776)) diff --git a/.changelog/v0.34.27/summary.md b/.changelog/v0.34.27/summary.md new file mode 100644 index 00000000000..e4a13db501b --- /dev/null +++ b/.changelog/v0.34.27/summary.md @@ -0,0 +1,17 @@ +*Feb 27, 2023* + +This is the first official release of CometBFT - a fork of [Tendermint +Core](https://github.com/tendermint/tendermint). This particular release is +intended to be compatible with the Tendermint Core v0.34 release series. + +For details as to how to upgrade to CometBFT from Tendermint Core, please see +our [upgrading guidelines](./UPGRADING.md). + +If you have any questions, comments, concerns or feedback on this release, we +would love to hear from you! Please contact us via [GitHub +Discussions](https://github.com/cometbft/cometbft/discussions), +[Discord](https://discord.gg/cosmosnetwork) (in the `#cometbft` channel) or +[Telegram](https://t.me/CometBFT). + +Special thanks to @wcsiu, @ze97286, @faddat and @JayT106 for their contributions +to this release! diff --git a/.changelog/v0.37.0/breaking-changes/211-deprecate-tmhome.md b/.changelog/v0.37.0/breaking-changes/211-deprecate-tmhome.md new file mode 100644 index 00000000000..547fc4e2d54 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/211-deprecate-tmhome.md @@ -0,0 +1,2 @@ +- The `TMHOME` environment variable was renamed to `CMTHOME`, and all environment variables starting with `TM_` are instead prefixed with `CMT_` + ([\#211](https://github.com/cometbft/cometbft/issues/211)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/230-p2p-peer-msg-type-and-metric.md b/.changelog/v0.37.0/breaking-changes/230-p2p-peer-msg-type-and-metric.md new file mode 100644 index 00000000000..5e7d11eae66 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/230-p2p-peer-msg-type-and-metric.md @@ -0,0 +1,4 @@ +- `[p2p]` Reactor `Send`, `TrySend` and `Receive` renamed to `SendEnvelope`, + `TrySendEnvelope` and `ReceiveEnvelope` to allow metrics to be appended to + messages and measure bytes sent/received. + ([\#230](https://github.com/cometbft/cometbft/pull/230)) diff --git a/.changelog/v0.37.0/breaking-changes/385-update-to-go1.20.md b/.changelog/v0.37.0/breaking-changes/385-update-to-go1.20.md new file mode 100644 index 00000000000..5e9ea3386ac --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/385-update-to-go1.20.md @@ -0,0 +1,2 @@ +- Bump minimum Go version to 1.20 + ([\#385](https://github.com/cometbft/cometbft/issues/385)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/409-deprecate-blocksyncmode b/.changelog/v0.37.0/breaking-changes/409-deprecate-blocksyncmode new file mode 100644 index 00000000000..a32707ad37d --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/409-deprecate-blocksyncmode @@ -0,0 +1,5 @@ +- [config] The boolean key `fastsync` is deprecated and replaced by + `block_sync`. ([\#9259](https://github.com/tendermint/tendermint/pull/9259)) + At the same time, `block_sync` is also deprecated. In the next release, + BlocSync will always be enabled and `block_sync` will be removed. + ([\#409](https://github.com/cometbft/cometbft/issues/409)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/5783-abci-lenght-delim.md b/.changelog/v0.37.0/breaking-changes/5783-abci-lenght-delim.md new file mode 100644 index 00000000000..d2b82c9bdd8 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/5783-abci-lenght-delim.md @@ -0,0 +1,3 @@ +- `[abci]` Make length delimiter encoding consistent + (`uint64`) between ABCI and P2P wire-level protocols + ([\#5783](https://github.com/tendermint/tendermint/pull/5783)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/6403-abci-events-mangled.md b/.changelog/v0.37.0/breaking-changes/6403-abci-events-mangled.md new file mode 100644 index 00000000000..e62e77327ce --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/6403-abci-events-mangled.md @@ -0,0 +1,3 @@ +- `[abci]` Change the `key` and `value` fields from + `[]byte` to `string` in the `EventAttribute` type. + ([\#6403](https://github.com/tendermint/tendermint/pull/6403)) diff --git a/.changelog/v0.37.0/breaking-changes/6684-abci-remove-counter-app.md b/.changelog/v0.37.0/breaking-changes/6684-abci-remove-counter-app.md new file mode 100644 index 00000000000..f990265a09b --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/6684-abci-remove-counter-app.md @@ -0,0 +1,2 @@ +- `[abci/counter]` Delete counter example app + ([\#6684](https://github.com/tendermint/tendermint/pull/6684)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/8216-abci-include-meaningful-headers.md b/.changelog/v0.37.0/breaking-changes/8216-abci-include-meaningful-headers.md new file mode 100644 index 00000000000..a09f8a56737 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/8216-abci-include-meaningful-headers.md @@ -0,0 +1,3 @@ +- `[abci]` Renamed `EvidenceType` to `MisbehaviorType` and `Evidence` + to `Misbehavior` as a more accurate label of their contents. + ([\#8216](https://github.com/tendermint/tendermint/pull/8216)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/8656-abci-cli-added-proposal-commands-a.md b/.changelog/v0.37.0/breaking-changes/8656-abci-cli-added-proposal-commands-a.md new file mode 100644 index 00000000000..3d70d40daaa --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/8656-abci-cli-added-proposal-commands-a.md @@ -0,0 +1,2 @@ +- `[abci]` Added cli commands for `PrepareProposal` and `ProcessProposal`. + ([\#8656](https://github.com/tendermint/tendermint/pull/8656)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/8901-abci-cli-added-proposal-commands-b.md b/.changelog/v0.37.0/breaking-changes/8901-abci-cli-added-proposal-commands-b.md new file mode 100644 index 00000000000..cdc7ff8bf46 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/8901-abci-cli-added-proposal-commands-b.md @@ -0,0 +1,2 @@ +- `[abci]` Added cli commands for `PrepareProposal` and `ProcessProposal`. + ([\#8901](https://github.com/tendermint/tendermint/pull/8901)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9122-abci-renamed-lastcommitinfo-commitinfo.md b/.changelog/v0.37.0/breaking-changes/9122-abci-renamed-lastcommitinfo-commitinfo.md new file mode 100644 index 00000000000..b679c1808b8 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9122-abci-renamed-lastcommitinfo-commitinfo.md @@ -0,0 +1,2 @@ +- `[abci]` Renamed `LastCommitInfo` to `CommitInfo` in preparation for vote + extensions. ([\#9122](https://github.com/tendermint/tendermint/pull/9122)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9144-change-english-speling.md b/.changelog/v0.37.0/breaking-changes/9144-change-english-speling.md new file mode 100644 index 00000000000..6a37394c74a --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9144-change-english-speling.md @@ -0,0 +1,3 @@ +- Change spelling from British English to American. Rename + `Subscription.Cancelled()` to `Subscription.Canceled()` in `libs/pubsub` + ([\#9144](https://github.com/tendermint/tendermint/pull/9144)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9145-abci-remove-setoption.md b/.changelog/v0.37.0/breaking-changes/9145-abci-remove-setoption.md new file mode 100644 index 00000000000..1332d9cb591 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9145-abci-remove-setoption.md @@ -0,0 +1,2 @@ +- `[abci]` Removes unused Response/Request `SetOption` from ABCI + ([\#9145](https://github.com/tendermint/tendermint/pull/9145)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9259-config-rename-fastsync-blocksync.md b/.changelog/v0.37.0/breaking-changes/9259-config-rename-fastsync-blocksync.md new file mode 100644 index 00000000000..228f6a08c79 --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9259-config-rename-fastsync-blocksync.md @@ -0,0 +1,3 @@ +- `[config]` Rename the fastsync section and the + fast\_sync key blocksync and block\_sync respectively + ([\#9259](https://github.com/tendermint/tendermint/pull/9259)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-a.md b/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-a.md new file mode 100644 index 00000000000..6e1ef58cb3f --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-a.md @@ -0,0 +1,5 @@ +- `[abci/params]` Deduplicate `ConsensusParams` and `BlockParams` so + only `types` proto definitions are use. Remove `TimeIotaMs` and use + a hard-coded 1 millisecond value to ensure monotonically increasing + block times. Rename `AppVersion` to `App` so as to not stutter. + ([\#9287](https://github.com/tendermint/tendermint/pull/9287)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-b.md b/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-b.md new file mode 100644 index 00000000000..88d3b08838c --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9287-abci-multiple-field-renaming-b.md @@ -0,0 +1,6 @@ +- `[types]` Reduce the use of protobuf types in core logic. `ConsensusParams`, + `BlockParams`, `ValidatorParams`, `EvidenceParams`, `VersionParams` have + become native types. They still utilize protobuf when being sent over + the wire or written to disk. Moved `ValidateConsensusParams` inside + (now native type) `ConsensusParams`, and renamed it to `ValidateBasic`. + ([\#9287](https://github.com/tendermint/tendermint/pull/9287)) \ No newline at end of file diff --git a/.changelog/v0.37.0/breaking-changes/9301-abci-add-v1-methods.md b/.changelog/v0.37.0/breaking-changes/9301-abci-add-v1-methods.md new file mode 100644 index 00000000000..efb1b95a1ad --- /dev/null +++ b/.changelog/v0.37.0/breaking-changes/9301-abci-add-v1-methods.md @@ -0,0 +1,3 @@ +- `[abci]` New ABCI methods `PrepareProposal` and `ProcessProposal` which give + the app control over transactions proposed and allows for verification of + proposed blocks. ([\#9301](https://github.com/tendermint/tendermint/pull/9301)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/382-txindexer-fix-slash-parsing.md b/.changelog/v0.37.0/bug-fixes/382-txindexer-fix-slash-parsing.md new file mode 100644 index 00000000000..8537c9d7377 --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/382-txindexer-fix-slash-parsing.md @@ -0,0 +1,4 @@ +- `[state/kvindexer]` Resolved crashes when event values contained slashes, + introduced after adding event sequences in + [\#77](https://github.com/cometbft/cometbft/pull/77). @jmalicevic + ([\#382](https://github.com/cometbft/cometbft/pull/382)) diff --git a/.changelog/v0.37.0/bug-fixes/386-quick-fix-needproofblock.md b/.changelog/v0.37.0/bug-fixes/386-quick-fix-needproofblock.md new file mode 100644 index 00000000000..2180086ce97 --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/386-quick-fix-needproofblock.md @@ -0,0 +1,2 @@ +- `[consensus]` ([\#386](https://github.com/cometbft/cometbft/pull/386)) Short-term fix for the case when `needProofBlock` cannot find previous block meta by defaulting to the creation of a new proof block. (@adizere) + - Special thanks to the [Vega.xyz](https://vega.xyz/) team, and in particular to Zohar (@ze97286), for reporting the problem and working with us to get to a fix. diff --git a/.changelog/v0.37.0/bug-fixes/4-busy-loop-send-block-part.md b/.changelog/v0.37.0/bug-fixes/4-busy-loop-send-block-part.md new file mode 100644 index 00000000000..59bda2afc3e --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/4-busy-loop-send-block-part.md @@ -0,0 +1,2 @@ +- `[consensus]` Fixed a busy loop that happened when sending of a block part failed by sleeping in case of error. + ([\#4](https://github.com/informalsystems/tendermint/pull/4)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/77-kvindexer-fix-evattribute-indexing.md b/.changelog/v0.37.0/bug-fixes/77-kvindexer-fix-evattribute-indexing.md new file mode 100644 index 00000000000..2d35d7e99d7 --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/77-kvindexer-fix-evattribute-indexing.md @@ -0,0 +1,4 @@ +- `[state/kvindexer]` Fixed the default behaviour of the kvindexer to index and + query attributes by events in which they occur. In 0.34.25 this was mitigated + by a separated RPC flag. @jmalicevic + ([\#77](https://github.com/cometbft/cometbft/pull/77)) diff --git a/.changelog/v0.37.0/bug-fixes/9073-docker-enable-cross-platform-build.md b/.changelog/v0.37.0/bug-fixes/9073-docker-enable-cross-platform-build.md new file mode 100644 index 00000000000..ef3891f5118 --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/9073-docker-enable-cross-platform-build.md @@ -0,0 +1,2 @@ +- `[docker]` enable cross platform build using docker buildx + ([\#9073](https://github.com/tendermint/tendermint/pull/9073)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/9229-consensus-fix-enterpropose-roundno.md b/.changelog/v0.37.0/bug-fixes/9229-consensus-fix-enterpropose-roundno.md new file mode 100644 index 00000000000..071f6210d19 --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/9229-consensus-fix-enterpropose-roundno.md @@ -0,0 +1,3 @@ +- `[consensus]` fix round number of `enterPropose` + when handling `RoundStepNewRound` timeout. + ([\#9229](https://github.com/tendermint/tendermint/pull/9229)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/9462-docker-use-right-go-version.md b/.changelog/v0.37.0/bug-fixes/9462-docker-use-right-go-version.md new file mode 100644 index 00000000000..16bee8a631c --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/9462-docker-use-right-go-version.md @@ -0,0 +1,2 @@ +- `[docker]` ensure Docker image uses consistent version of Go + ([\#9462](https://github.com/tendermint/tendermint/pull/9462)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/9500-p2p-prevent-adding-errored-peers.md b/.changelog/v0.37.0/bug-fixes/9500-p2p-prevent-adding-errored-peers.md new file mode 100644 index 00000000000..41038ddb62e --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/9500-p2p-prevent-adding-errored-peers.md @@ -0,0 +1,2 @@ +- `[p2p]` prevent peers who have errored from being added to `peer_set` + ([\#9500](https://github.com/tendermint/tendermint/pull/9500)) \ No newline at end of file diff --git a/.changelog/v0.37.0/bug-fixes/9518-blocksync-handle-senqueueue-full.md b/.changelog/v0.37.0/bug-fixes/9518-blocksync-handle-senqueueue-full.md new file mode 100644 index 00000000000..b486654b17d --- /dev/null +++ b/.changelog/v0.37.0/bug-fixes/9518-blocksync-handle-senqueueue-full.md @@ -0,0 +1,3 @@ +- `[blocksync]` handle the case when the sending + queue is full: retry block request after a timeout + ([\#9518](https://github.com/tendermint/tendermint/pull/9518)) \ No newline at end of file diff --git a/.changelog/v0.37.0/features/9301-abci-add-v1-methods.md b/.changelog/v0.37.0/features/9301-abci-add-v1-methods.md new file mode 100644 index 00000000000..efb1b95a1ad --- /dev/null +++ b/.changelog/v0.37.0/features/9301-abci-add-v1-methods.md @@ -0,0 +1,3 @@ +- `[abci]` New ABCI methods `PrepareProposal` and `ProcessProposal` which give + the app control over transactions proposed and allows for verification of + proposed blocks. ([\#9301](https://github.com/tendermint/tendermint/pull/9301)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/136-remove-tm-signer-harness.md b/.changelog/v0.37.0/improvements/136-remove-tm-signer-harness.md new file mode 100644 index 00000000000..6eb6c2158c2 --- /dev/null +++ b/.changelog/v0.37.0/improvements/136-remove-tm-signer-harness.md @@ -0,0 +1,2 @@ +- `[tools/tm-signer-harness]` Remove the folder as it is unused + ([\#136](https://github.com/cometbft/cometbft/issues/136)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/230-p2p-peer-msg-type-and-metric.md b/.changelog/v0.37.0/improvements/230-p2p-peer-msg-type-and-metric.md new file mode 100644 index 00000000000..6eeede4c728 --- /dev/null +++ b/.changelog/v0.37.0/improvements/230-p2p-peer-msg-type-and-metric.md @@ -0,0 +1,4 @@ +- `[p2p]` Reactor `Send`, `TrySend` and `Receive` renamed to `SendEnvelope`, + `TrySendEnvelope` and `ReceiveEnvelope` to allow metrics to be appended to + messages and measure bytes sent/received. + ([\#230](https://github.com/cometbft/cometbft/pull/230)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/56-rpc-cache-rpc-responses.md b/.changelog/v0.37.0/improvements/56-rpc-cache-rpc-responses.md new file mode 100644 index 00000000000..344b3df93b9 --- /dev/null +++ b/.changelog/v0.37.0/improvements/56-rpc-cache-rpc-responses.md @@ -0,0 +1,2 @@ +- `[e2e]` Add functionality for uncoordinated (minor) upgrades + ([\#56](https://github.com/tendermint/tendermint/pull/56)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/5706-abci-add-version-plus-info.md b/.changelog/v0.37.0/improvements/5706-abci-add-version-plus-info.md new file mode 100644 index 00000000000..1225ec4769a --- /dev/null +++ b/.changelog/v0.37.0/improvements/5706-abci-add-version-plus-info.md @@ -0,0 +1,3 @@ +- `[abci]` Added `AbciVersion` to `RequestInfo` allowing + applications to check ABCI version when connecting to CometBFT. + ([\#5706](https://github.com/tendermint/tendermint/pull/5706)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/9171-cli-add-hard-flag.md b/.changelog/v0.37.0/improvements/9171-cli-add-hard-flag.md new file mode 100644 index 00000000000..febc57f4265 --- /dev/null +++ b/.changelog/v0.37.0/improvements/9171-cli-add-hard-flag.md @@ -0,0 +1,4 @@ +- `[cli]` add `--hard` flag to rollback command (and a boolean to the `RollbackState` method). This will rollback + state and remove the last block. This command can be triggered multiple times. The application must also rollback + state to the same height. + ([\#9171](https://github.com/tendermint/tendermint/pull/9171)) diff --git a/.changelog/v0.37.0/improvements/9250-crypto-update-btcec-btcutil.md b/.changelog/v0.37.0/improvements/9250-crypto-update-btcec-btcutil.md new file mode 100644 index 00000000000..3c3bd0ec304 --- /dev/null +++ b/.changelog/v0.37.0/improvements/9250-crypto-update-btcec-btcutil.md @@ -0,0 +1,2 @@ +- `[crypto]` Update to use btcec v2 and the latest btcutil. + ([\#9250](https://github.com/tendermint/tendermint/pull/9250)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/9276-rpc-add-header-queries.md b/.changelog/v0.37.0/improvements/9276-rpc-add-header-queries.md new file mode 100644 index 00000000000..9daeac4cab3 --- /dev/null +++ b/.changelog/v0.37.0/improvements/9276-rpc-add-header-queries.md @@ -0,0 +1,2 @@ +- `[rpc]` Added `header` and `header_by_hash` queries to the RPC client + ([\#9276](https://github.com/tendermint/tendermint/pull/9276)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/9356-proto-use-cosmos-gogo.md b/.changelog/v0.37.0/improvements/9356-proto-use-cosmos-gogo.md new file mode 100644 index 00000000000..c64b6def3bf --- /dev/null +++ b/.changelog/v0.37.0/improvements/9356-proto-use-cosmos-gogo.md @@ -0,0 +1,2 @@ +- `[proto]` Migrate from `gogo/protobuf` to `cosmos/gogoproto` + ([\#9356](https://github.com/tendermint/tendermint/pull/9356)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/9650-rpc-enable-caching.md b/.changelog/v0.37.0/improvements/9650-rpc-enable-caching.md new file mode 100644 index 00000000000..3b6b5034726 --- /dev/null +++ b/.changelog/v0.37.0/improvements/9650-rpc-enable-caching.md @@ -0,0 +1,2 @@ +- `[rpc]` Enable caching of RPC responses + ([\#9650](https://github.com/tendermint/tendermint/pull/9650)) \ No newline at end of file diff --git a/.changelog/v0.37.0/improvements/9760-consensus-ref-to-previous-height-precommits.md b/.changelog/v0.37.0/improvements/9760-consensus-ref-to-previous-height-precommits.md new file mode 100644 index 00000000000..4763bd2d39e --- /dev/null +++ b/.changelog/v0.37.0/improvements/9760-consensus-ref-to-previous-height-precommits.md @@ -0,0 +1,2 @@ +- `[consensus]` Save peer LastCommit correctly to achieve 50% reduction in gossiped precommits. + ([\#9760](https://github.com/tendermint/tendermint/pull/9760)) \ No newline at end of file diff --git a/.changelog/v0.37.0/summary.md b/.changelog/v0.37.0/summary.md new file mode 100644 index 00000000000..b96e98f5e96 --- /dev/null +++ b/.changelog/v0.37.0/summary.md @@ -0,0 +1,25 @@ +*March 6, 2023* + +This is the first CometBFT release with ABCI 1.0, which introduces the +`PrepareProposal` and `ProcessProposal` methods, with the aim of expanding the +range of use cases that application developers can address. This is the first +change to ABCI towards ABCI++, and the full range of ABCI++ functionality will +only become available in the next major release with ABCI 2.0. See the +[specification](./spec/abci/) for more details. + +In the v0.34.27 release, the CometBFT Go module is still +`github.com/tendermint/tendermint` to facilitate ease of upgrading for users, +but in this release we have changed this to `github.com/cometbft/cometbft`. + +Please also see our [upgrading guidelines](./UPGRADING.md) for more details on +upgrading from the v0.34 release series. + +Also see our [QA results](https://docs.cometbft.com/v0.37/qa/v037/cometbft) for +the v0.37 release. + +We'd love your feedback on this release! Please reach out to us via one of our +communication channels, such as [GitHub +Discussions](https://github.com/cometbft/cometbft/discussions), with any of your +questions, comments and/or concerns. + +See below for more details. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 41e45f8611d..579466cdcb7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,7 @@ jobs: goos: ["linux"] timeout-minutes: 5 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" - uses: actions/checkout@v3 @@ -42,7 +42,7 @@ jobs: needs: build timeout-minutes: 5 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" - uses: actions/checkout@v3 @@ -64,7 +64,7 @@ jobs: needs: build timeout-minutes: 5 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" - uses: actions/checkout@v3 diff --git a/.github/workflows/check-generated.yml b/.github/workflows/check-generated.yml index f15f78012ef..45bec88585a 100644 --- a/.github/workflows/check-generated.yml +++ b/.github/workflows/check-generated.yml @@ -16,7 +16,7 @@ jobs: check-mocks: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" @@ -41,7 +41,7 @@ jobs: check-proto: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" diff --git a/.github/workflows/cometbft-docker.yml b/.github/workflows/cometbft-docker.yml index 6324feaa443..f55725d8b3d 100644 --- a/.github/workflows/cometbft-docker.yml +++ b/.github/workflows/cometbft-docker.yml @@ -41,7 +41,7 @@ jobs: platforms: all - name: Set up Docker Build - uses: docker/setup-buildx-action@v2.4.1 + uses: docker/setup-buildx-action@v2.5.0 - name: Login to DockerHub if: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/e2e-long-main.yml b/.github/workflows/e2e-long-main.yml index fb4af3a6029..302e29d1ecb 100644 --- a/.github/workflows/e2e-long-main.yml +++ b/.github/workflows/e2e-long-main.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 120 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/e2e-manual-multiversion.yml b/.github/workflows/e2e-manual-multiversion.yml index 62d5a6acdf4..9332ef91d49 100644 --- a/.github/workflows/e2e-manual-multiversion.yml +++ b/.github/workflows/e2e-manual-multiversion.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/e2e-manual.yml b/.github/workflows/e2e-manual.yml index 9c31a82cdbe..302e83bb940 100644 --- a/.github/workflows/e2e-manual.yml +++ b/.github/workflows/e2e-manual.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/e2e-nightly-34x.yml b/.github/workflows/e2e-nightly-34x.yml index 8d89a20dabd..fa234c02bf9 100644 --- a/.github/workflows/e2e-nightly-34x.yml +++ b/.github/workflows/e2e-nightly-34x.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.18' diff --git a/.github/workflows/e2e-nightly-37x.yml b/.github/workflows/e2e-nightly-37x.yml index 4d672e6c18d..056ae1355f4 100644 --- a/.github/workflows/e2e-nightly-37x.yml +++ b/.github/workflows/e2e-nightly-37x.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/e2e-nightly-main.yml b/.github/workflows/e2e-nightly-main.yml index fd7c47fb993..52ec6b083dd 100644 --- a/.github/workflows/e2e-nightly-main.yml +++ b/.github/workflows/e2e-nightly-main.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 917670bd738..e6a4a7e730f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' - uses: actions/checkout@v3 diff --git a/.github/workflows/fuzz-nightly.yml b/.github/workflows/fuzz-nightly.yml index c9093756c7d..15a20f06407 100644 --- a/.github/workflows/fuzz-nightly.yml +++ b/.github/workflows/fuzz-nightly.yml @@ -13,7 +13,7 @@ jobs: fuzz-nightly-test: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index 2fd82b36599..f7e1e10818a 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -15,7 +15,7 @@ jobs: govulncheck: runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20.2" - uses: actions/checkout@v3 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f3bcb920d12..b3271d53895 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -20,7 +20,7 @@ jobs: timeout-minutes: 8 steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' - uses: technote-space/get-diff-action@v6 diff --git a/.github/workflows/markdown-links.yml b/.github/workflows/markdown-links.yml deleted file mode 100644 index d9de1359fce..00000000000 --- a/.github/workflows/markdown-links.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Check Markdown links - -on: - schedule: - # 2am UTC daily - - cron: '0 2 * * *' - -jobs: - markdown-link-check: - strategy: - matrix: - branch: ['main', 'v0.37.x', 'v0.34.x'] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ matrix.branch }} - - uses: informalsystems/github-action-markdown-link-check@main - with: - config-file: '.md-link-check.json' diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 226db58652a..bbd28cbd067 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -16,7 +16,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/proto-lint.yml b/.github/workflows/proto-lint.yml index e2f9b9d5289..55f5feff79a 100644 --- a/.github/workflows/proto-lint.yml +++ b/.github/workflows/proto-lint.yml @@ -15,7 +15,7 @@ jobs: timeout-minutes: 5 steps: - uses: actions/checkout@v3 - - uses: bufbuild/buf-setup-action@v1.14.0 + - uses: bufbuild/buf-setup-action@v1.15.1 - uses: bufbuild/buf-lint-action@v1 with: input: 'proto' diff --git a/.github/workflows/release-version.yml b/.github/workflows/release-version.yml index 6fbaf57a91a..773e9339ab3 100644 --- a/.github/workflows/release-version.yml +++ b/.github/workflows/release-version.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 51cc1288bea..e1c959c3f32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: '1.20' diff --git a/.github/workflows/testapp-docker.yml b/.github/workflows/testapp-docker.yml index 0e77cec5f34..d503a9868f7 100644 --- a/.github/workflows/testapp-docker.yml +++ b/.github/workflows/testapp-docker.yml @@ -41,7 +41,7 @@ jobs: platforms: all - name: Set up Docker Build - uses: docker/setup-buildx-action@v2.4.1 + uses: docker/setup-buildx-action@v2.5.0 - name: Login to DockerHub if: ${{ github.event_name != 'pull_request' }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 48e435b0e73..69801355d55 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: matrix: part: ["00", "01", "02", "03", "04", "05"] steps: - - uses: actions/setup-go@v3 + - uses: actions/setup-go@v4 with: go-version: "1.20" - uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 749235b3afb..fd6c3aab928 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,56 +1,236 @@ # CHANGELOG -## Unreleased +## v0.37.0 + +*March 6, 2023* + +This is the first CometBFT release with ABCI 1.0, which introduces the +`PrepareProposal` and `ProcessProposal` methods, with the aim of expanding the +range of use cases that application developers can address. This is the first +change to ABCI towards ABCI++, and the full range of ABCI++ functionality will +only become available in the next major release with ABCI 2.0. See the +[specification](./spec/abci/) for more details. + +In the v0.34.27 release, the CometBFT Go module is still +`github.com/tendermint/tendermint` to facilitate ease of upgrading for users, +but in this release we have changed this to `github.com/cometbft/cometbft`. + +Please also see our [upgrading guidelines](./UPGRADING.md) for more details on +upgrading from the v0.34 release series. + +Also see our [QA results](https://docs.cometbft.com/v0.37/qa/v037/cometbft) for +the v0.37 release. + +We'd love your feedback on this release! Please reach out to us via one of our +communication channels, such as [GitHub +Discussions](https://github.com/cometbft/cometbft/discussions), with any of your +questions, comments and/or concerns. + +See below for more details. ### BREAKING CHANGES -- `[tools/tm-signer-harness]` Set OS home dir to instead of the hardcoded PATH. - ([\#6498](https://github.com/tendermint/tendermint/pull/6498)) -- `[state]` Move pruneBlocks from node/state to state/execution. - ([\#6541](https://github.com/tendermint/tendermint/pull/6541)) -- `[p2p]` Remove unused p2p/trust package - ([\#9625](https://github.com/tendermint/tendermint/pull/9625)) -- `[rpc]` Remove global environment and replace with constructor - ([\#9655](https://github.com/tendermint/tendermint/pull/9655)) -- `[node]` Move DBContext and DBProvider from the node package to the config - package. ([\#9655](https://github.com/tendermint/tendermint/pull/9655)) -- `[inspect]` Add a new `inspect` command for introspecting - the state and block store of a crashed tendermint node. - ([\#9655](https://github.com/tendermint/tendermint/pull/9655)) -- `[metrics]` Move state-syncing and block-syncing metrics to - their respective packages. Move labels from block_syncing - -> blocksync_syncing and state_syncing -> statesync_syncing - ([\#9682](https://github.com/tendermint/tendermint/pull/9682)) +- The `TMHOME` environment variable was renamed to `CMTHOME`, and all environment variables starting with `TM_` are instead prefixed with `CMT_` + ([\#211](https://github.com/cometbft/cometbft/issues/211)) +- `[p2p]` Reactor `Send`, `TrySend` and `Receive` renamed to `SendEnvelope`, + `TrySendEnvelope` and `ReceiveEnvelope` to allow metrics to be appended to + messages and measure bytes sent/received. + ([\#230](https://github.com/cometbft/cometbft/pull/230)) +- Bump minimum Go version to 1.20 + ([\#385](https://github.com/cometbft/cometbft/issues/385)) +- `[abci]` Make length delimiter encoding consistent + (`uint64`) between ABCI and P2P wire-level protocols + ([\#5783](https://github.com/tendermint/tendermint/pull/5783)) +- `[abci]` Change the `key` and `value` fields from + `[]byte` to `string` in the `EventAttribute` type. + ([\#6403](https://github.com/tendermint/tendermint/pull/6403)) +- `[abci/counter]` Delete counter example app + ([\#6684](https://github.com/tendermint/tendermint/pull/6684)) +- `[abci]` Renamed `EvidenceType` to `MisbehaviorType` and `Evidence` + to `Misbehavior` as a more accurate label of their contents. + ([\#8216](https://github.com/tendermint/tendermint/pull/8216)) +- `[abci]` Added cli commands for `PrepareProposal` and `ProcessProposal`. + ([\#8656](https://github.com/tendermint/tendermint/pull/8656)) +- `[abci]` Added cli commands for `PrepareProposal` and `ProcessProposal`. + ([\#8901](https://github.com/tendermint/tendermint/pull/8901)) +- `[abci]` Renamed `LastCommitInfo` to `CommitInfo` in preparation for vote + extensions. ([\#9122](https://github.com/tendermint/tendermint/pull/9122)) +- Change spelling from British English to American. Rename + `Subscription.Cancelled()` to `Subscription.Canceled()` in `libs/pubsub` + ([\#9144](https://github.com/tendermint/tendermint/pull/9144)) +- `[abci]` Removes unused Response/Request `SetOption` from ABCI + ([\#9145](https://github.com/tendermint/tendermint/pull/9145)) +- `[config]` Rename the fastsync section and the + fast\_sync key blocksync and block\_sync respectively + ([\#9259](https://github.com/tendermint/tendermint/pull/9259)) +- `[types]` Reduce the use of protobuf types in core logic. `ConsensusParams`, + `BlockParams`, `ValidatorParams`, `EvidenceParams`, `VersionParams` have + become native types. They still utilize protobuf when being sent over + the wire or written to disk. Moved `ValidateConsensusParams` inside + (now native type) `ConsensusParams`, and renamed it to `ValidateBasic`. + ([\#9287](https://github.com/tendermint/tendermint/pull/9287)) +- `[abci/params]` Deduplicate `ConsensusParams` and `BlockParams` so + only `types` proto definitions are use. Remove `TimeIotaMs` and use + a hard-coded 1 millisecond value to ensure monotonically increasing + block times. Rename `AppVersion` to `App` so as to not stutter. + ([\#9287](https://github.com/tendermint/tendermint/pull/9287)) +- `[abci]` New ABCI methods `PrepareProposal` and `ProcessProposal` which give + the app control over transactions proposed and allows for verification of + proposed blocks. ([\#9301](https://github.com/tendermint/tendermint/pull/9301)) ### BUG FIXES -- `[docker]` Ensure Docker image uses consistent version of Go. +- `[consensus]` Fixed a busy loop that happened when sending of a block part failed by sleeping in case of error. + ([\#4](https://github.com/informalsystems/tendermint/pull/4)) +- `[state/kvindexer]` Fixed the default behaviour of the kvindexer to index and + query attributes by events in which they occur. In 0.34.25 this was mitigated + by a separated RPC flag. @jmalicevic + ([\#77](https://github.com/cometbft/cometbft/pull/77)) +- `[state/kvindexer]` Resolved crashes when event values contained slashes, + introduced after adding event sequences in + [\#77](https://github.com/cometbft/cometbft/pull/77). @jmalicevic + ([\#382](https://github.com/cometbft/cometbft/pull/382)) +- `[consensus]` ([\#386](https://github.com/cometbft/cometbft/pull/386)) Short-term fix for the case when `needProofBlock` cannot find previous block meta by defaulting to the creation of a new proof block. (@adizere) + - Special thanks to the [Vega.xyz](https://vega.xyz/) team, and in particular to Zohar (@ze97286), for reporting the problem and working with us to get to a fix. +- `[docker]` enable cross platform build using docker buildx + ([\#9073](https://github.com/tendermint/tendermint/pull/9073)) +- `[consensus]` fix round number of `enterPropose` + when handling `RoundStepNewRound` timeout. + ([\#9229](https://github.com/tendermint/tendermint/pull/9229)) +- `[docker]` ensure Docker image uses consistent version of Go ([\#9462](https://github.com/tendermint/tendermint/pull/9462)) -- `[abci-cli]` Fix broken abci-cli help command. - ([\#9717](https://github.com/tendermint/tendermint/pull/9717)) +- `[p2p]` prevent peers who have errored from being added to `peer_set` + ([\#9500](https://github.com/tendermint/tendermint/pull/9500)) +- `[blocksync]` handle the case when the sending + queue is full: retry block request after a timeout + ([\#9518](https://github.com/tendermint/tendermint/pull/9518)) ### FEATURES -- `[config]` Introduce `BootstrapPeers` to the config to allow - nodes to list peers to be added to the addressbook upon start up. - ([\#9680](https://github.com/tendermint/tendermint/pull/9680)) -- `[proxy]` Introduce `NewUnsyncLocalClientCreator`, which allows local ABCI - clients to have the same concurrency model as remote clients (i.e. one - mutex per client "connection", for each of the four ABCI "connections"). - ([\#9830](https://github.com/tendermint/tendermint/pull/9830)) +- `[abci]` New ABCI methods `PrepareProposal` and `ProcessProposal` which give + the app control over transactions proposed and allows for verification of + proposed blocks. ([\#9301](https://github.com/tendermint/tendermint/pull/9301)) ### IMPROVEMENTS -- `[crypto/merkle]` Improve HashAlternatives performance - ([\#6443](https://github.com/tendermint/tendermint/pull/6443)) -- `[p2p/pex]` Improve addrBook.hash performance - ([\#6509](https://github.com/tendermint/tendermint/pull/6509)) -- `[crypto/merkle]` Improve HashAlternatives performance - ([\#6513](https://github.com/tendermint/tendermint/pull/6513)) -- `[pubsub]` Performance improvements for the event query API - ([\#7319](https://github.com/tendermint/tendermint/pull/7319)) +- `[e2e]` Add functionality for uncoordinated (minor) upgrades + ([\#56](https://github.com/tendermint/tendermint/pull/56)) +- `[tools/tm-signer-harness]` Remove the folder as it is unused + ([\#136](https://github.com/cometbft/cometbft/issues/136)) +- `[p2p]` Reactor `Send`, `TrySend` and `Receive` renamed to `SendEnvelope`, + `TrySendEnvelope` and `ReceiveEnvelope` to allow metrics to be appended to + messages and measure bytes sent/received. + ([\#230](https://github.com/cometbft/cometbft/pull/230)) +- `[abci]` Added `AbciVersion` to `RequestInfo` allowing + applications to check ABCI version when connecting to CometBFT. + ([\#5706](https://github.com/tendermint/tendermint/pull/5706)) +- `[cli]` add `--hard` flag to rollback command (and a boolean to the `RollbackState` method). This will rollback + state and remove the last block. This command can be triggered multiple times. The application must also rollback + state to the same height. + ([\#9171](https://github.com/tendermint/tendermint/pull/9171)) +- `[crypto]` Update to use btcec v2 and the latest btcutil. + ([\#9250](https://github.com/tendermint/tendermint/pull/9250)) +- `[rpc]` Added `header` and `header_by_hash` queries to the RPC client + ([\#9276](https://github.com/tendermint/tendermint/pull/9276)) +- `[proto]` Migrate from `gogo/protobuf` to `cosmos/gogoproto` + ([\#9356](https://github.com/tendermint/tendermint/pull/9356)) - `[rpc]` Enable caching of RPC responses ([\#9650](https://github.com/tendermint/tendermint/pull/9650)) +- `[consensus]` Save peer LastCommit correctly to achieve 50% reduction in gossiped precommits. + ([\#9760](https://github.com/tendermint/tendermint/pull/9760)) + +## v0.34.27 + +*Feb 27, 2023* + +This is the first official release of CometBFT - a fork of [Tendermint +Core](https://github.com/tendermint/tendermint). This particular release is +intended to be compatible with the Tendermint Core v0.34 release series. + +For details as to how to upgrade to CometBFT from Tendermint Core, please see +our [upgrading guidelines](./UPGRADING.md). + +If you have any questions, comments, concerns or feedback on this release, we +would love to hear from you! Please contact us via [GitHub +Discussions](https://github.com/cometbft/cometbft/discussions), +[Discord](https://discord.gg/cosmosnetwork) (in the `#cometbft` channel) or +[Telegram](https://t.me/CometBFT). + +Special thanks to @wcsiu, @ze97286, @faddat and @JayT106 for their contributions +to this release! + +### BREAKING CHANGES + +- Rename binary to `cometbft` and Docker image to `cometbft/cometbft` + ([\#152](https://github.com/cometbft/cometbft/pull/152)) +- The `TMHOME` environment variable was renamed to `CMTHOME`, and all + environment variables starting with `TM_` are instead prefixed with `CMT_` + ([\#211](https://github.com/cometbft/cometbft/issues/211)) +- Use Go 1.19 to build CometBFT, since Go 1.18 has reached end-of-life. + ([\#360](https://github.com/cometbft/cometbft/issues/360)) + +### BUG FIXES + +- `[consensus]` Fixed a busy loop that happened when sending of a block part + failed by sleeping in case of error. + ([\#4](https://github.com/informalsystems/tendermint/pull/4)) +- `[state/kvindexer]` Resolved crashes when event values contained slashes, + introduced after adding event sequences. + (\#[383](https://github.com/cometbft/cometbft/pull/383): @jmalicevic) +- `[consensus]` Short-term fix for the case when `needProofBlock` cannot find + previous block meta by defaulting to the creation of a new proof block. + ([\#386](https://github.com/cometbft/cometbft/pull/386): @adizere) + - Special thanks to the [Vega.xyz](https://vega.xyz/) team, and in particular + to Zohar (@ze97286), for reporting the problem and working with us to get to + a fix. +- `[p2p]` Correctly use non-blocking `TrySendEnvelope` method when attempting to + send messages, as opposed to the blocking `SendEnvelope` method. It is unclear + whether this has a meaningful impact on P2P performance, but this patch does + correct the underlying behaviour to what it should be + ([tendermint/tendermint\#9936](https://github.com/tendermint/tendermint/pull/9936)) + +### DEPENDENCIES + +- Replace [tm-db](https://github.com/tendermint/tm-db) with + [cometbft-db](https://github.com/cometbft/cometbft-db) + ([\#160](https://github.com/cometbft/cometbft/pull/160)) +- Bump tm-load-test to v1.3.0 to remove implicit dependency on Tendermint Core + ([\#165](https://github.com/cometbft/cometbft/pull/165)) +- `[crypto]` Update to use btcec v2 and the latest btcutil + ([tendermint/tendermint\#9787](https://github.com/tendermint/tendermint/pull/9787): + @wcsiu) + +### FEATURES + +- `[rpc]` Add `match_event` query parameter to indicate to the RPC that it + should match events _within_ attributes, not only within a height + ([tendermint/tendermint\#9759](https://github.com/tendermint/tendermint/pull/9759)) + +### IMPROVEMENTS + +- `[e2e]` Add functionality for uncoordinated (minor) upgrades + ([\#56](https://github.com/tendermint/tendermint/pull/56)) +- `[tools/tm-signer-harness]` Remove the folder as it is unused + ([\#136](https://github.com/cometbft/cometbft/issues/136)) +- Append the commit hash to the version of CometBFT being built + ([\#204](https://github.com/cometbft/cometbft/pull/204)) +- `[mempool/v1]` Suppress "rejected bad transaction" in priority mempool logs by + reducing log level from info to debug + ([\#314](https://github.com/cometbft/cometbft/pull/314): @JayT106) +- `[consensus]` Add `consensus_block_gossip_parts_received` and + `consensus_step_duration_seconds` metrics in order to aid in investigating the + impact of database compaction on consensus performance + ([tendermint/tendermint\#9733](https://github.com/tendermint/tendermint/pull/9733)) +- `[state/kvindexer]` Add `match.event` keyword to support condition evaluation + based on the event the attributes belong to + ([tendermint/tendermint\#9759](https://github.com/tendermint/tendermint/pull/9759)) +- `[p2p]` Reduce log spam through reducing log level of "Dialing peer" and + "Added peer" messages from info to debug + ([tendermint/tendermint\#9764](https://github.com/tendermint/tendermint/pull/9764): + @faddat) +- `[consensus]` Reduce bandwidth consumption of consensus votes by roughly 50% + through fixing a small logic bug + ([tendermint/tendermint\#9776](https://github.com/tendermint/tendermint/pull/9776)) --- diff --git a/Makefile b/Makefile index 7551602f64d..0d63f4a8dc4 100644 --- a/Makefile +++ b/Makefile @@ -1,52 +1,12 @@ +include common.mk + PACKAGES=$(shell go list ./...) BUILDDIR?=$(CURDIR)/build OUTPUT?=$(BUILDDIR)/cometbft -BUILD_TAGS?=cometbft - -COMMIT_HASH := $(shell git rev-parse --short HEAD) -LD_FLAGS = -X github.com/cometbft/cometbft/version.TMGitCommitHash=$(COMMIT_HASH) -BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)" HTTPS_GIT := https://github.com/cometbft/cometbft.git CGO_ENABLED ?= 0 -# handle nostrip -ifeq (,$(findstring nostrip,$(COMETBFT_BUILD_OPTIONS))) - BUILD_FLAGS += -trimpath - LD_FLAGS += -s -w -endif - -# handle race -ifeq (race,$(findstring race,$(COMETBFT_BUILD_OPTIONS))) - CGO_ENABLED=1 - BUILD_FLAGS += -race -endif - -# handle cleveldb -ifeq (cleveldb,$(findstring cleveldb,$(COMETBFT_BUILD_OPTIONS))) - CGO_ENABLED=1 - BUILD_TAGS += cleveldb -endif - -# handle badgerdb -ifeq (badgerdb,$(findstring badgerdb,$(COMETBFT_BUILD_OPTIONS))) - BUILD_TAGS += badgerdb -endif - -# handle rocksdb -ifeq (rocksdb,$(findstring rocksdb,$(COMETBFT_BUILD_OPTIONS))) - CGO_ENABLED=1 - BUILD_TAGS += rocksdb -endif - -# handle boltdb -ifeq (boltdb,$(findstring boltdb,$(COMETBFT_BUILD_OPTIONS))) - BUILD_TAGS += boltdb -endif - -# allow users to pass additional flags via the conventional LDFLAGS variable -LD_FLAGS += $(LDFLAGS) - # Process Docker environment varible TARGETPLATFORM # in order to build binary with correspondent ARCH # by default will always build for linux/amd64 diff --git a/README.md b/README.md index 973c5996def..2d39be1faa3 100644 --- a/README.md +++ b/README.md @@ -60,17 +60,17 @@ looking for, see [our security policy](SECURITY.md). | CometBFT version | Requirement | Notes | |------------------|-------------|-------------------| -| v0.34.x | Go version | Go 1.19 or higher | -| v0.37.x | Go version | Go 1.20 or higher | | main | Go version | Go 1.20 or higher | +| v0.37.x | Go version | Go 1.20 or higher | +| v0.34.x | Go version | Go 1.19 or higher | ### Install -See the [install instructions](./docs/introduction/install.md). +See the [install guide](./docs/guides/install.md). ### Quick Start -- [Single node](./docs/introduction/quick-start.md) +- [Single node](./docs/guides/quick-start.md) - [Local cluster using docker-compose](./docs/networks/docker-compose.md) ## Contributing @@ -120,9 +120,10 @@ CometBFT up-to-date. Upgrading instructions can be found in Currently supported versions include: +- v0.37.x: CometBFT v0.37 introduces ABCI 1.0, which is the first major step + towards the full ABCI++ implementation in ABCI 2.0 - v0.34.x: The CometBFT v0.34 series is compatible with the Tendermint Core v0.34 series -- v0.37.x: (release candidate) ## Resources diff --git a/UPGRADING.md b/UPGRADING.md index ab8b9820249..cec35029b87 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -17,12 +17,31 @@ This guide provides instructions for upgrading to specific versions of CometBFT. * Config fields `TTLDuration` and `TTLNumBlocks`, which were only used by the priority mempool, have been removed. +### Mempool Changes + +* The priority mempool (what was referred in the code as version `v1`) has been + removed. There is now only one mempool (what was called version `v0`), that + is, the default implementation as a queue of transactions. +* In the protobuf message `ResponseCheckTx`, fields `sender`, `priority`, and + `mempool_error`, which were only used by the priority mempool, were removed + but still kept in the message as "reserved". + +## v0.37.0 + +This release introduces state machine-breaking changes, and therefore requires a +coordinated upgrade. + +### Go API + +When upgrading from the v0.34 release series, please note that the Go module has +now changed to `github.com/cometbft/cometbft`. + ### ABCI Changes * The `ABCIVersion` is now `2.0.0`. * Added new ABCI methods `ExtendVote`, and `VerifyVoteExtension`. Applications upgrading to v0.38.0 must implement these methods as described - [here](./spec/abci/abci++_app_requirements.md) + [here](./spec/abci/abci%2B%2B_comet_expected_behavior.md#adapting-existing-applications-that-use-abci) * Removed methods `BeginBlock`, `DeliverTx`, `EndBlock`, and replaced them by method `FinalizeBlock`. Applications upgrading to v0.38.0 must refactor the logic handling the methods removed to handle `FinalizeBlock`. @@ -33,11 +52,71 @@ This guide provides instructions for upgrading to specific versions of CometBFT. * For details, please see the updated [specification](spec/abci/README.md) -### Mempool Changes +### RPC -* The priority mempool (what was referred in the code as version `v1`) has been - removed. There is now only one mempool (what was called version `v0`), that - is, the default implementation as a queue of transactions. -* In the protobuf message `ResponseCheckTx`, fields `sender`, `priority`, and - `mempool_error`, which were only used by the priority mempool, were removed - but still kept in the message as "reserved". +If you rely on the `/tx_search` or `/block_search` endpoints for event querying, +please note that the default behaviour of these endpoints has changed in a way +that might break your queries. The original behaviour was poorly specified, +which did not respect event boundaries. + +Please see +[tendermint/tendermint\#9712](https://github.com/tendermint/tendermint/issues/9712) +for context on the bug that was addressed that resulted in this behaviour +change. + +## v0.34.27 + +This is the first official release of CometBFT, forked originally from +[Tendermint Core v0.34.24][v03424] and subsequently updated in Informal Systems' +public fork of Tendermint Core for [v0.34.25][v03425] and [v0.34.26][v03426]. + +### Upgrading from Tendermint Core + +If you already make use of Tendermint Core (either the original Tendermint Core +v0.34.24, or Informal Systems' public fork), you can upgrade to CometBFT +v0.34.27 by replacing your dependency in your `go.mod` file: + +```bash +go mod edit -replace github.com/tendermint/tendermint=github.com/cometbft/cometbft@v0.34.27 +``` + +We make use of the original module URL in order to minimize the impact of +switching to CometBFT. This is only possible in our v0.34 release series, and we +will be switching our module URL to `github.com/cometbft/cometbft` in the next +major release. + +### Home directory + +CometBFT, by default, will consider its home directory in `~/.cometbft` from now +on instead of `~/.tendermint`. + +### Environment variables + +The environment variable prefixes have now changed from `TM` to `CMT`. For +example, `TMHOME` or `TM_HOME` become `CMTHOME` or `CMT_HOME`. + +We have implemented a fallback check in case `TMHOME` is still set and `CMTHOME` +is not, but you will start to see a warning message in the logs if the old +`TMHOME` variable is set. This fallback check will be removed entirely in a +subsequent major release of CometBFT. + +### Building CometBFT + +CometBFT must be compiled using Go 1.19 or higher. The use of Go 1.18 is not +supported, since this version has reached end-of-life with the release of [Go 1.20][go120]. + +### Troubleshooting + +If you run into any trouble with this upgrade, please [contact us][discussions]. + +--- + +For historical upgrading instructions for Tendermint Core v0.34.24 and earlier, +please see the [Tendermint Core upgrading instructions][tmupgrade]. + +[v03424]: https://github.com/tendermint/tendermint/releases/tag/v0.34.24 +[v03425]: https://github.com/informalsystems/tendermint/releases/tag/v0.34.25 +[v03426]: https://github.com/informalsystems/tendermint/releases/tag/v0.34.26 +[discussions]: https://github.com/cometbft/cometbft/discussions +[tmupgrade]: https://github.com/tendermint/tendermint/blob/35581cf54ec436b8c37fabb43fdaa3f48339a170/UPGRADING.md +[go120]: https://go.dev/blog/go1.20 diff --git a/abci/example/kvstore/kvstore.go b/abci/example/kvstore/kvstore.go index ec5ff6524bc..0f8794893b3 100644 --- a/abci/example/kvstore/kvstore.go +++ b/abci/example/kvstore/kvstore.go @@ -45,6 +45,10 @@ type Application struct { // validator set valUpdates []types.ValidatorUpdate valAddrToPubKeyMap map[string]cryptoproto.PublicKey + + // If true, the app will generate block events in BeginBlock. Used to test the event indexer + // Should be false by default to avoid generating too much data. + genBlockEvents bool } // NewApplication creates an instance of the kvstore from the provided database @@ -72,6 +76,10 @@ func NewInMemoryApplication() *Application { return NewApplication(dbm.NewMemDB()) } +func (app *Application) SetGenBlockEvents() { + app.genBlockEvents = true +} + // Info returns information about the state of the application. This is generally used everytime a Tendermint instance // begins and let's the application know what Tendermint versions it's interacting with. Based from this information, // Tendermint will ensure it is in sync with the application by potentially replaying the blocks it has. If the @@ -217,6 +225,14 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal } else { app.stagedTxs = append(app.stagedTxs, tx) } + + var key, value string + parts := bytes.Split(tx, []byte("=")) + if len(parts) == 2 { + key, value = string(parts[0]), string(parts[1]) + } else { + key, value = string(tx), string(tx) + } respTxs[i] = &types.ExecTxResult{ Code: CodeTypeOK, // With every transaction we can emit a series of events. To make it simple, we just emit the same events. @@ -225,6 +241,16 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal Type: "app", Attributes: []types.EventAttribute{ {Key: "creator", Value: "Cosmoshi Netowoko", Index: true}, + {Key: "key", Value: key, Index: true}, + {Key: "index_key", Value: "index is working", Index: true}, + {Key: "noindex_key", Value: "index is working", Index: false}, + }, + }, + { + Type: "app", + Attributes: []types.EventAttribute{ + {Key: "creator", Value: "Cosmoshi", Index: true}, + {Key: "key", Value: value, Index: true}, {Key: "index_key", Value: "index is working", Index: true}, {Key: "noindex_key", Value: "index is working", Index: false}, }, @@ -236,7 +262,63 @@ func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinal app.state.Height = req.Height - return &types.ResponseFinalizeBlock{TxResults: respTxs, ValidatorUpdates: app.valUpdates, AppHash: app.state.Hash()}, nil + response := &types.ResponseFinalizeBlock{TxResults: respTxs, ValidatorUpdates: app.valUpdates, AppHash: app.state.Hash()} + if !app.genBlockEvents { + return response, nil + } + if app.state.Height%2 == 0 { + response.Events = []types.Event{ + { + Type: "begin_event", + Attributes: []types.EventAttribute{ + { + Key: "foo", + Value: "100", + Index: true, + }, + { + Key: "bar", + Value: "200", + Index: true, + }, + }, + }, + { + Type: "begin_event", + Attributes: []types.EventAttribute{ + { + Key: "foo", + Value: "200", + Index: true, + }, + { + Key: "bar", + Value: "300", + Index: true, + }, + }, + }, + } + } else { + response.Events = []types.Event{ + { + Type: "begin_event", + Attributes: []types.EventAttribute{ + { + Key: "foo", + Value: "400", + Index: true, + }, + { + Key: "bar", + Value: "300", + Index: true, + }, + }, + }, + } + } + return response, nil } // Commit is called after FinalizeBlock and after Tendermint state which includes the updates to diff --git a/blocksync/metrics.gen.go b/blocksync/metrics.gen.go index 1d093fb314f..46c24df208d 100644 --- a/blocksync/metrics.gen.go +++ b/blocksync/metrics.gen.go @@ -20,11 +20,39 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics { Name: "syncing", Help: "Whether or not a node is block syncing. 1 if yes, 0 if no.", }, labels).With(labelsAndValues...), + NumTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "num_txs", + Help: "Number of transactions in the latest block.", + }, labels).With(labelsAndValues...), + TotalTxs: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "total_txs", + Help: "Total number of transactions.", + }, labels).With(labelsAndValues...), + BlockSizeBytes: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "block_size_bytes", + Help: "Size of the latest block.", + }, labels).With(labelsAndValues...), + LatestBlockHeight: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: MetricsSubsystem, + Name: "latest_block_height", + Help: "The height of the latest block.", + }, labels).With(labelsAndValues...), } } func NopMetrics() *Metrics { return &Metrics{ - Syncing: discard.NewGauge(), + Syncing: discard.NewGauge(), + NumTxs: discard.NewGauge(), + TotalTxs: discard.NewGauge(), + BlockSizeBytes: discard.NewGauge(), + LatestBlockHeight: discard.NewGauge(), } } diff --git a/blocksync/metrics.go b/blocksync/metrics.go index 78a6337b945..f120b4f7c44 100644 --- a/blocksync/metrics.go +++ b/blocksync/metrics.go @@ -1,6 +1,7 @@ package blocksync import ( + "github.com/cometbft/cometbft/types" "github.com/go-kit/kit/metrics" ) @@ -16,4 +17,19 @@ const ( type Metrics struct { // Whether or not a node is block syncing. 1 if yes, 0 if no. Syncing metrics.Gauge + // Number of transactions in the latest block. + NumTxs metrics.Gauge + // Total number of transactions. + TotalTxs metrics.Gauge + // Size of the latest block. + BlockSizeBytes metrics.Gauge + // The height of the latest block. + LatestBlockHeight metrics.Gauge +} + +func (m *Metrics) recordBlockMetrics(block *types.Block) { + m.NumTxs.Set(float64(len(block.Data.Txs))) + m.TotalTxs.Add(float64(len(block.Data.Txs))) + m.BlockSizeBytes.Set(float64(block.Size())) + m.LatestBlockHeight.Set(float64(block.Height)) } diff --git a/blocksync/reactor.go b/blocksync/reactor.go index cb7ec1555c7..b67c2d844c4 100644 --- a/blocksync/reactor.go +++ b/blocksync/reactor.go @@ -502,6 +502,7 @@ FOR_LOOP: // TODO This is bad, are we zombie? panic(fmt.Sprintf("Failed to process committed block (%d:%X): %v", first.Height, first.Hash(), err)) } + bcR.metrics.recordBlockMetrics(first) blocksSynced++ if blocksSynced%100 == 0 { diff --git a/cmd/cometbft/commands/run_node.go b/cmd/cometbft/commands/run_node.go index 5d7005635a1..2765b92e6e1 100644 --- a/cmd/cometbft/commands/run_node.go +++ b/cmd/cometbft/commands/run_node.go @@ -31,7 +31,6 @@ func AddNodeFlags(cmd *cobra.Command) { "socket address to listen on for connections from external priv_validator process") // node flags - cmd.Flags().Bool("block_sync", config.BlockSyncMode, "sync the block chain using the blocksync algorithm") cmd.Flags().BytesHexVar( &genesisHash, "genesis_hash", diff --git a/common.mk b/common.mk new file mode 100644 index 00000000000..2ab35eaf1d0 --- /dev/null +++ b/common.mk @@ -0,0 +1,43 @@ +# This contains Makefile logic that is common to several makefiles + +BUILD_TAGS ?= cometbft + +COMMIT_HASH := $(shell git rev-parse --short HEAD) +LD_FLAGS = -X github.com/cometbft/cometbft/version.TMGitCommitHash=$(COMMIT_HASH) +BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)" +# allow users to pass additional flags via the conventional LDFLAGS variable +LD_FLAGS += $(LDFLAGS) + +# handle nostrip +ifeq (,$(findstring nostrip,$(COMETBFT_BUILD_OPTIONS))) + BUILD_FLAGS += -trimpath + LD_FLAGS += -s -w +endif + +# handle race +ifeq (race,$(findstring race,$(COMETBFT_BUILD_OPTIONS))) + CGO_ENABLED=1 + BUILD_FLAGS += -race +endif + +# handle cleveldb +ifeq (cleveldb,$(findstring cleveldb,$(COMETBFT_BUILD_OPTIONS))) + CGO_ENABLED=1 + BUILD_TAGS += cleveldb +endif + +# handle badgerdb +ifeq (badgerdb,$(findstring badgerdb,$(COMETBFT_BUILD_OPTIONS))) + BUILD_TAGS += badgerdb +endif + +# handle rocksdb +ifeq (rocksdb,$(findstring rocksdb,$(COMETBFT_BUILD_OPTIONS))) + CGO_ENABLED=1 + BUILD_TAGS += rocksdb +endif + +# handle boltdb +ifeq (boltdb,$(findstring boltdb,$(COMETBFT_BUILD_OPTIONS))) + BUILD_TAGS += boltdb +endif diff --git a/config/config.go b/config/config.go index ccb7e9928ae..00127a550b9 100644 --- a/config/config.go +++ b/config/config.go @@ -179,11 +179,6 @@ type BaseConfig struct { //nolint: maligned // A custom human readable name for this node Moniker string `mapstructure:"moniker"` - // If this node is many blocks behind the tip of the chain, Blocksync - // allows them to catchup quickly by downloading blocks in parallel - // and verifying their commits - BlockSyncMode bool `mapstructure:"block_sync"` - // Database backend: goleveldb | cleveldb | boltdb | rocksdb // * goleveldb (github.com/syndtr/goleveldb - most popular implementation) // - pure go @@ -251,7 +246,6 @@ func DefaultBaseConfig() BaseConfig { ABCI: "socket", LogLevel: DefaultLogLevel, LogFormat: LogFormatPlain, - BlockSyncMode: true, FilterPeers: false, DBBackend: "goleveldb", DBPath: DefaultDataDir, @@ -262,7 +256,6 @@ func DefaultBaseConfig() BaseConfig { func TestBaseConfig() BaseConfig { cfg := DefaultBaseConfig() cfg.ProxyApp = "kvstore" - cfg.BlockSyncMode = false cfg.DBBackend = "memdb" return cfg } diff --git a/config/toml.go b/config/toml.go index a6ee895e965..598f40f1967 100644 --- a/config/toml.go +++ b/config/toml.go @@ -89,11 +89,6 @@ proxy_app = "{{ .BaseConfig.ProxyApp }}" # A custom human readable name for this node moniker = "{{ .BaseConfig.Moniker }}" -# If this node is many blocks behind the tip of the chain, BlockSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -block_sync = {{ .BaseConfig.BlockSyncMode }} - # Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb # * goleveldb (github.com/syndtr/goleveldb - most popular implementation) # - pure go diff --git a/config/toml_test.go b/config/toml_test.go index 6455bc98670..58a103e9371 100644 --- a/config/toml_test.go +++ b/config/toml_test.go @@ -66,7 +66,6 @@ func assertValidConfig(t *testing.T, configFile string) { "moniker", "seeds", "proxy_app", - "block_sync", "create_empty_blocks", "peer", "timeout", diff --git a/consensus/metrics.go b/consensus/metrics.go index dbdc078975f..ab2b78d476d 100644 --- a/consensus/metrics.go +++ b/consensus/metrics.go @@ -8,7 +8,6 @@ import ( cstypes "github.com/cometbft/cometbft/consensus/types" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - "github.com/cometbft/cometbft/types" ) const ( @@ -119,14 +118,6 @@ type Metrics struct { LateVotes metrics.Counter `metrics_labels:"vote_type"` } -// RecordConsMetrics uses for recording the block related metrics during fast-sync. -func (m *Metrics) RecordConsMetrics(block *types.Block) { - m.NumTxs.Set(float64(len(block.Data.Txs))) - m.TotalTxs.Add(float64(len(block.Data.Txs))) - m.BlockSizeBytes.Set(float64(block.Size())) - m.CommittedHeight.Set(float64(block.Height)) -} - func (m *Metrics) MarkProposalProcessed(accepted bool) { status := "accepted" if !accepted { diff --git a/consensus/reactor.go b/consensus/reactor.go index 0aa579218f0..1d7655ae26b 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -1062,8 +1062,8 @@ func (ps *PeerState) GetRoundState() *cstypes.PeerRoundState { return &prs } -// ToJSON returns a json of PeerState. -func (ps *PeerState) ToJSON() ([]byte, error) { +// MarshalJSON implements the json.Marshaler interface. +func (ps *PeerState) MarshalJSON() ([]byte, error) { ps.mtx.Lock() defer ps.mtx.Unlock() diff --git a/consensus/state.go b/consensus/state.go index 14b71da089b..47a4c733fcb 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -1752,8 +1752,7 @@ func (cs *State) finalizeCommit(height int64) { block, ) if err != nil { - logger.Error("failed to apply block", "err", err) - return + panic(fmt.Sprintf("failed to apply block; error %v", err)) } fail.Fail() // XXX diff --git a/docs/README.md b/docs/README.md index 453d9cd91ec..c13ca2f4ca7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,9 +16,9 @@ CometBFT serves blockchain applications. More formally, CometBFT performs Byzantine Fault Tolerant (BFT) State Machine Replication (SMR) for arbitrary deterministic, finite state machines. -For more background, see [What is CometBFT?](introduction/what-is-cometbft.md). +For more background, see [What is CometBFT?](introduction/README.md#what-is-cometbft.md). -To get started quickly with an example application, see the [quick start guide](introduction/quick-start.md). +To get started quickly with an example application, see the [quick start guide](guides/quick-start.md). To learn about application development on CometBFT, see the [Application Blockchain Interface](https://github.com/cometbft/cometbft/tree/main/spec/abci). diff --git a/docs/app-dev/indexing-transactions.md b/docs/app-dev/indexing-transactions.md index 46f72b94f03..c5b3205381e 100644 --- a/docs/app-dev/indexing-transactions.md +++ b/docs/app-dev/indexing-transactions.md @@ -5,17 +5,19 @@ order: 6 # Indexing Transactions CometBFT allows you to index transactions and blocks and later query or -subscribe to their results. Transactions are indexed by `TxResult.Events` and -blocks are indexed by `Response(Begin|End)Block.Events`. However, transactions +subscribe to their results. Transactions are indexed by `ResponseFinalizeBlock.tx_results.events` and +blocks are indexed by `ResponseFinalizeBlock.events`. However, transactions are also indexed by a primary key which includes the transaction hash and maps -to and stores the corresponding `TxResult`. Blocks are indexed by a primary key +to and stores the corresponding transaction results. Blocks are indexed by a primary key which includes the block height and maps to and stores the block height, i.e. the block itself is never stored. Each event contains a type and a list of attributes, which are key-value pairs denoting something about what happened during the method's execution. For more details on `Events`, see the + [ABCI](https://github.com/cometbft/cometbft/blob/main/spec/abci/abci++_basic_concepts.md#events) + documentation. An `Event` has a composite key associated with it. A `compositeKey` is @@ -34,6 +36,9 @@ would be equal to the composite key of `jack.account.number`. By default, CometBFT will index all transactions by their respective hashes and height and blocks by their height. +CometBFT allows for different events within the same height to have +equal attributes. + ## Configuration Operators can configure indexing via the `[tx_index]` section. The `indexer` @@ -67,6 +72,60 @@ for block and transaction events directly against CometBFT's RPC. However, the query syntax is limited and so this indexer type might be deprecated or removed entirely in the future. +**Implementation and data layout** + +The kv indexer stores each attribute of an event individually, by creating a composite key +with +- event type, +- attribute key, +- attribute value, +- event generator (e.g. `FinalizeBlock`) +- the height, and +- event counter. + For example the following events: + +``` +Type: "transfer", + Attributes: []abci.EventAttribute{ + {Key: "sender", Value: "Bob", Index: true}, + {Key: "recipient", Value: "Alice", Index: true}, + {Key: "balance", Value: "100", Index: true}, + {Key: "note", Value: "nothing", Index: true}, + }, + +``` + +``` +Type: "transfer", + Attributes: []abci.EventAttribute{ + {Key: "sender", Value: "Tom", Index: true}, + {Key: "recipient", Value: "Alice", Index: true}, + {Key: "balance", Value: "200", Index: true}, + {Key: "note", Value: "nothing", Index: true}, + }, +``` + +will be represented as follows in the store, assuming these events result from the `finalize_block` call for height 1: + +``` +Key value +---- event1 ------ +transferSenderBobFinalizeBlock11 1 +transferRecipientAliceFinalizeBlock11 1 +transferBalance100FinalizeBlock11 1 +transferNodeNothingFinalizeBlock11 1 +---- event2 ------ +transferSenderTomFinalizeBlock12 1 +transferRecepientAliceFinalizeBlock12 1 +transferBalance200FinalizeBlock12 1 +transferNodeNothingFinalizeBlock12 1 + +``` +The event number is a local variable kept by the indexer and incremented when a new event is processed. +It is an `int64` variable and has no other semantics besides being used to associate attributes belonging to the same events within a height. +This variable is not atomically incremented as event indexing is deterministic. **Should this ever change**, the event id generation +will be broken. + #### PostgreSQL The `psql` indexer type allows an operator to enable block and transaction event @@ -109,27 +168,58 @@ The following indexes are indexed by default: Applications are free to define which events to index. CometBFT does not expose functionality to define which events to index and which to ignore. In -your application's `DeliverTx` method, add the `Events` field with pairs of +your application's `FinalizeBlock` method, add the `Events` field with pairs of UTF-8 encoded strings (e.g. "transfer.sender": "Bob", "transfer.recipient": "Alice", "transfer.balance": "100"). Example: ```go -func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.Result { +func (app *Application) FinalizeBlock(_ context.Context, req *types.RequestFinalizeBlock) (*types.ResponseFinalizeBlock, error) { + //... - events := []abci.Event{ - { - Type: "transfer", - Attributes: []abci.EventAttribute{ - {Key: []byte("sender"), Value: []byte("Bob"), Index: true}, - {Key: []byte("recipient"), Value: []byte("Alice"), Index: true}, - {Key: []byte("balance"), Value: []byte("100"), Index: true}, - {Key: []byte("note"), Value: []byte("nothing"), Index: true}, - }, - }, - } - return types.ResponseDeliverTx{Code: code.CodeTypeOK, Events: events} + tx_results[0] := &types.ExecTxResult{ + Code: CodeTypeOK, + // With every transaction we can emit a series of events. To make it simple, we just emit the same events. + Events: []types.Event{ + { + Type: "app", + Attributes: []types.EventAttribute{ + {Key: "creator", Value: "Cosmoshi Netowoko", Index: true}, + {Key: "key", Value: key, Index: true}, + {Key: "index_key", Value: "index is working", Index: true}, + {Key: "noindex_key", Value: "index is working", Index: false}, + }, + }, + { + Type: "app", + Attributes: []types.EventAttribute{ + {Key: "creator", Value: "Cosmoshi", Index: true}, + {Key: "key", Value: value, Index: true}, + {Key: "index_key", Value: "index is working", Index: true}, + {Key: "noindex_key", Value: "index is working", Index: false}, + }, + }, + }, + } + + block_events = []types.Event{ + { + Type: "loan", + Attributes: []types.EventAttribute{ + { Key: "account_no", Value: "1", Index: true}, + { Key: "amount", Value: "200", Index: true }, + }, + }, + { + Type: "loan", + Attributes: []types.EventAttribute{ + { Key: "account_no", Value: "2", Index: true }, + { Key: "amount", Value: "300", Index: true}, + }, + }, + } + return &types.ResponseFinalizeBlock{TxResults: tx_results, Events: block_events} } ``` @@ -168,7 +258,7 @@ a query to `/subscribe` RPC endpoint. Check out [API docs](https://docs.cometbft.com/main/rpc/#subscribe) for more information on query syntax and other options. -## Querying Blocks Events +## Querying Block Events You can query for a paginated set of blocks by their events by calling the `/block_search` RPC endpoint: @@ -177,5 +267,12 @@ You can query for a paginated set of blocks by their events by calling the curl "localhost:26657/block_search?query=\"block.height > 10 AND val_set.num_changed > 0\"" ``` -Check out [API docs](https://docs.cometbft.com/main/rpc/#/Info/block_search) -for more information on query syntax and other options. + +Storing the event sequence was introduced in CometBFT 0.34.26. Before that, up until Tendermint Core 0.34.26, +the event sequence was not stored in the kvstore and events were stored only by height. That means that queries +returned blocks and transactions whose event attributes match within the height but can match across different +events on that height. +This behavior was fixed with CometBFT 0.34.26+. However, if the data was indexed with earlier versions of +Tendermint Core and not re-indexed, that data will be queried as if all the attributes within a height +occurred within the same event. + diff --git a/docs/core/block-sync.md b/docs/core/block-sync.md index 487ce7c73ba..aac917180ed 100644 --- a/docs/core/block-sync.md +++ b/docs/core/block-sync.md @@ -18,17 +18,14 @@ consensus gossip protocol. ## Using Block Sync -To support faster syncing, CometBFT offers a `block-sync` mode, which -is enabled by default, and can be toggled in the `config.toml` or via -`--block_sync=false`. - -In this mode, the CometBFT daemon will sync hundreds of times faster -than if it used the real-time consensus process. Once caught up, the -daemon will switch out of Block Sync and into the normal consensus mode. -After running for some time, the node is considered `caught up` if it -has at least one peer and its height is at least as high as the max -reported peer height. -See [the IsCaughtUp method](https://github.com/cometbft/cometbft/blob/main/blocksync/pool.go#L168). +When starting from scratch, nodes will use the Block Sync mode. +In this mode, the CometBFT daemon +will sync hundreds of times faster than if it used the real-time consensus +process. Once caught up, the daemon will switch out of Block Sync and into the +normal consensus mode. After running for some time, the node is considered +`caught up` if it has at least one peer and its height is at least as high as +the max reported peer height. See [the IsCaughtUp +method](https://github.com/cometbft/cometbft/blob/main/blocksync/pool.go#L168). Note: While there have historically been multiple versions of blocksync, v0, v1, and v2, all versions other than v0 have been deprecated in favor of the simplest and most well understood algorithm. diff --git a/docs/core/configuration.md b/docs/core/configuration.md index 37b9e3de519..63c8e723ea8 100644 --- a/docs/core/configuration.md +++ b/docs/core/configuration.md @@ -36,11 +36,6 @@ proxy_app = "tcp://127.0.0.1:26658" # A custom human readable name for this node moniker = "anonymous" -# If this node is many blocks behind the tip of the chain, BlockSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -block_sync = true - # Database backend: goleveldb | cleveldb | boltdb | rocksdb | badgerdb # * goleveldb (github.com/syndtr/goleveldb - most popular implementation) # - pure go diff --git a/docs/core/running-in-production.md b/docs/core/running-in-production.md index 02f88e765d8..beaee33056e 100644 --- a/docs/core/running-in-production.md +++ b/docs/core/running-in-production.md @@ -93,16 +93,39 @@ mechanisms. ### RPC +#### Attack Exposure and Mitigation + +**It is generally not recommended for RPC endpoints to be exposed publicly, and +especially so if the node in question is a validator**, as the CometBFT RPC does +not currently provide advanced security features. Public exposure of RPC +endpoints without appropriate protection can make the associated node vulnerable +to a variety of attacks. + +It is entirely up to operators to ensure, if nodes' RPC endpoints have to be +exposed publicly, that appropriate measures have been taken to mitigate against +attacks. Some examples of mitigation measures include, but are not limited to: + +- Never publicly exposing the RPC endpoints of validators (i.e. if the RPC + endpoints absolutely have to be exposed, ensure you do so only on full nodes + and with appropriate protection) +- Correct usage of rate-limiting, authentication and caching (e.g. as provided + by reverse proxies like [nginx](https://nginx.org/) and/or DDoS protection + services like [Cloudflare](https://www.cloudflare.com)) +- Only exposing the specific endpoints absolutely necessary for the relevant use + cases (configurable via nginx/Cloudflare/etc.) + +If no expertise is available to the operator to assist with securing nodes' RPC +endpoints, it is strongly recommended to never expose those endpoints publicly. + +**Under no condition should any of the [unsafe RPC endpoints](../rpc/#/Unsafe) +ever be exposed publicly.** + +#### Endpoints Returning Multiple Entries + Endpoints returning multiple entries are limited by default to return 30 elements (100 max). See the [RPC Documentation](https://docs.cometbft.com/main/rpc/) for more information. -Rate-limiting and authentication are another key aspects to help protect -against DOS attacks. Validators are supposed to use external tools like -[NGINX](https://www.nginx.com/blog/rate-limiting-nginx/) or -[traefik](https://doc.traefik.io/traefik/middlewares/http/ratelimit/) -to achieve the same things. - ## Debugging CometBFT If you ever have to debug CometBFT, the first thing you should probably do is diff --git a/docs/tutorials/README.md b/docs/guides/README.md similarity index 65% rename from docs/tutorials/README.md rename to docs/guides/README.md index 8a7fda4ca11..b563396313a 100644 --- a/docs/tutorials/README.md +++ b/docs/guides/README.md @@ -6,5 +6,7 @@ parent: # Guides +- [Installing CometBFT](./install.md) +- [Quick-start using CometBFT](./quick-start.md) - [Creating a built-in application in Go](./go-built-in.md) - [Creating an external application in Go](./go.md) diff --git a/docs/tutorials/go-built-in.md b/docs/guides/go-built-in.md similarity index 99% rename from docs/tutorials/go-built-in.md rename to docs/guides/go-built-in.md index 74f0df7b425..c0e780bf95c 100644 --- a/docs/tutorials/go-built-in.md +++ b/docs/guides/go-built-in.md @@ -86,8 +86,7 @@ CometBFT, `v0.37.0` in this example. ```bash go mod init kvstore -go get github.com/tendermint/tendermint -go mod edit -replace github.com/tendermint/tendermint=github.com/cometbft/cometbft@v0.34.27 +go get github.com/cometbft/cometbft@v0.37.0 ``` After running the above commands you will see two generated files, `go.mod` and `go.sum`. diff --git a/docs/tutorials/go.md b/docs/guides/go.md similarity index 100% rename from docs/tutorials/go.md rename to docs/guides/go.md diff --git a/docs/introduction/install.md b/docs/guides/install.md similarity index 100% rename from docs/introduction/install.md rename to docs/guides/install.md diff --git a/docs/introduction/quick-start.md b/docs/guides/quick-start.md similarity index 98% rename from docs/introduction/quick-start.md rename to docs/guides/quick-start.md index 06d2df0aeea..b0eecf25187 100644 --- a/docs/introduction/quick-start.md +++ b/docs/guides/quick-start.md @@ -11,7 +11,7 @@ works and want to get started right away, continue. ## Install -See the [install instructions](./install.md). +See the [install guide](./install.md). ## Initialization diff --git a/docs/introduction/README.md b/docs/introduction/README.md index 1e85ba5295d..acafe992f59 100644 --- a/docs/introduction/README.md +++ b/docs/introduction/README.md @@ -5,16 +5,327 @@ parent: order: 1 --- -# Overview +# What is CometBFT -## Quick Start +CometBFT is software for securely and consistently replicating an +application on many machines. By securely, we mean that CometBFT works +as long as less than 1/3 of machines fail in arbitrary ways. By consistently, +we mean that every non-faulty machine sees the same transaction log and +computes the same state. Secure and consistent replication is a +fundamental problem in distributed systems; it plays a critical role in +the fault tolerance of a broad range of applications, from currencies, +to elections, to infrastructure orchestration, and beyond. -Get CometBFT up-and-running quickly with the [quick-start guide](./quick-start.md)! +The ability to tolerate machines failing in arbitrary ways, including +becoming malicious, is known as Byzantine fault tolerance (BFT). The +theory of BFT is decades old, but software implementations have only +became popular recently, due largely to the success of "blockchain +technology" like Bitcoin and Ethereum. Blockchain technology is just a +reformalization of BFT in a more modern setting, with emphasis on +peer-to-peer networking and cryptographic authentication. The name +derives from the way transactions are batched in blocks, where each +block contains a cryptographic hash of the previous one, forming a +chain. -## Install +CometBFT consists of two chief technical components: a blockchain +consensus engine and a generic application interface. +The consensus engine, +which is based on [Tendermint consensus algorithm][tendermint-paper], +ensures that the same transactions are +recorded on every machine in the same order. The application interface, +called the Application BlockChain Interface (ABCI), delivers the transactions +to applications for processing. Unlike other +blockchain and consensus solutions, which come pre-packaged with built +in state machines (like a fancy key-value store, or a quirky scripting +language), developers can use CometBFT for BFT state machine +replication of applications written in whatever programming language and +development environment is right for them. -Detailed [installation instructions](./install.md). +CometBFT is designed to be easy-to-use, simple-to-understand, highly +performant, and useful for a wide variety of distributed applications. -## What is CometBFT +## CometBFT vs. X -Dive into [what CometBFT is and why](./what-is-cometbft.md)! +CometBFT is broadly similar to two classes of software. The first +class consists of distributed key-value stores, like Zookeeper, etcd, +and consul, which use non-BFT consensus. The second class is known as +"blockchain technology", and consists of both cryptocurrencies like +Bitcoin and Ethereum, and alternative distributed ledger designs like +Hyperledger's Burrow. + +### Zookeeper, etcd, consul + +Zookeeper, etcd, and consul are all implementations of key-value stores +atop a classical, non-BFT consensus algorithm. Zookeeper uses an +algorithm called Zookeeper Atomic Broadcast, while etcd and consul use +the Raft log replication algorithm. A +typical cluster contains 3-5 machines, and can tolerate crash failures +in less than 1/2 of the machines (e.g., 1 out of 3 or 2 out of 5), +but even a single Byzantine fault can jeopardize the whole system. + +Each offering provides a slightly different implementation of a +featureful key-value store, but all are generally focused around +providing basic services to distributed systems, such as dynamic +configuration, service discovery, locking, leader-election, and so on. + +CometBFT is in essence similar software, but with two key differences: + +- It is Byzantine Fault Tolerant, meaning it can only tolerate less than 1/3 + of machines failing, but those failures can include arbitrary behavior - + including hacking and malicious attacks. +- It does not specify a + particular application, like a fancy key-value store. Instead, it + focuses on arbitrary state machine replication, so developers can build + the application logic that's right for them, from key-value store to + cryptocurrency to e-voting platform and beyond. + +### Bitcoin, Ethereum, etc + +[Tendermint consensus algorithm][tendermint-paper], adopted by CometBFT, +emerged in the tradition of cryptocurrencies like Bitcoin, +Ethereum, etc. with the goal of providing a more efficient and secure +consensus algorithm than Bitcoin's Proof of Work. In the early days, +Tendermint consensus-based blockchains had a simple currency built in, and to participate in +consensus, users had to "bond" units of the currency into a security +deposit which could be revoked if they misbehaved -this is what made +Tendermint consensus a Proof-of-Stake algorithm. + +Since then, CometBFT has evolved to be a general purpose blockchain +consensus engine that can host arbitrary application states. That means +it can be used as a plug-and-play replacement for the consensus engines +of other blockchain software. So one can take the current Ethereum code +base, whether in Rust, or Go, or Haskell, and run it as an ABCI +application using CometBFT. Indeed, [we did that with +Ethereum](https://github.com/cosmos/ethermint). And we plan to do +the same for Bitcoin, ZCash, and various other deterministic +applications as well. + +Another example of a cryptocurrency application built on CometBFT is +[the Cosmos network](http://cosmos.network). + +### Other Blockchain Projects + +[Fabric](https://github.com/hyperledger/fabric) takes a similar approach +to CometBFT, but is more opinionated about how the state is managed, +and requires that all application behavior runs in potentially many +docker containers, modules it calls "chaincode". It uses an +implementation of [PBFT](http://pmg.csail.mit.edu/papers/osdi99.pdf). +from a team at IBM that is [augmented to handle potentially +non-deterministic +chaincode](https://drops.dagstuhl.de/opus/volltexte/2017/7093/pdf/LIPIcs-OPODIS-2016-24.pdf). +It is possible to implement this docker-based behavior as an ABCI app in +CometBFT, though extending CometBFT to handle non-determinism +remains for future work. + +[Burrow](https://github.com/hyperledger/burrow) is an implementation of +the Ethereum Virtual Machine and Ethereum transaction mechanics, with +additional features for a name-registry, permissions, and native +contracts, and an alternative blockchain API. It uses CometBFT as its +consensus engine, and provides a particular application state. + +## ABCI Overview + +The [Application BlockChain Interface +(ABCI)](https://github.com/cometbft/cometbft/tree/main/abci) +allows for Byzantine Fault Tolerant replication of applications +written in any programming language. + +### Motivation + +Thus far, all blockchains "stacks" (such as +[Bitcoin](https://github.com/bitcoin/bitcoin)) have had a monolithic +design. That is, each blockchain stack is a single program that handles +all the concerns of a decentralized ledger; this includes P2P +connectivity, the "mempool" broadcasting of transactions, consensus on +the most recent block, account balances, Turing-complete contracts, +user-level permissions, etc. + +Using a monolithic architecture is typically bad practice in computer +science. It makes it difficult to reuse components of the code, and +attempts to do so result in complex maintenance procedures for forks of +the codebase. This is especially true when the codebase is not modular +in design and suffers from "spaghetti code". + +Another problem with monolithic design is that it limits you to the +language of the blockchain stack (or vice versa). In the case of +Ethereum which supports a Turing-complete bytecode virtual-machine, it +limits you to languages that compile down to that bytecode; while the +[list](https://github.com/pirapira/awesome-ethereum-virtual-machine#programming-languages-that-compile-into-evm) +is growing, it is still very limited. + +In contrast, our approach is to decouple the consensus engine and P2P +layers from the details of the state of the particular +blockchain application. We do this by abstracting away the details of +the application to an interface, which is implemented as a socket +protocol. + +### Intro to ABCI + +[CometBFT](https://github.com/cometbft/cometbft), the +"consensus engine", communicates with the application via a socket +protocol that satisfies the ABCI, the CometBFT Socket Protocol. + +To draw an analogy, let's talk about a well-known cryptocurrency, +Bitcoin. Bitcoin is a cryptocurrency blockchain where each node +maintains a fully audited Unspent Transaction Output (UTXO) database. If +one wanted to create a Bitcoin-like system on top of ABCI, CometBFT +would be responsible for + +- Sharing blocks and transactions between nodes +- Establishing a canonical/immutable order of transactions + (the blockchain) + +The application will be responsible for + +- Maintaining the UTXO database +- Validating cryptographic signatures of transactions +- Preventing transactions from spending non-existent transactions +- Allowing clients to query the UTXO database. + +CometBFT is able to decompose the blockchain design by offering a very +simple API (i.e. the ABCI) between the application process and consensus +process. + +The ABCI consists of 3 primary message types that get delivered from the +core to the application. The application replies with corresponding +response messages. + +The messages are specified here: [ABCI Message +Types](https://github.com/cometbft/cometbft/blob/main/proto/tendermint/abci/types.proto). + +The **DeliverTx** message is the work horse of the application. Each +transaction in the blockchain is delivered with this message. The +application needs to validate each transaction received with the +**DeliverTx** message against the current state, application protocol, +and the cryptographic credentials of the transaction. A validated +transaction then needs to update the application state — by binding a +value into a key values store, or by updating the UTXO database, for +instance. + +The **CheckTx** message is similar to **DeliverTx**, but it's only for +validating transactions. CometBFT's mempool first checks the +validity of a transaction with **CheckTx**, and only relays valid +transactions to its peers. For instance, an application may check an +incrementing sequence number in the transaction and return an error upon +**CheckTx** if the sequence number is old. Alternatively, they might use +a capabilities based system that requires capabilities to be renewed +with every transaction. + +The **Commit** message is used to compute a cryptographic commitment to +the current application state, to be placed into the next block header. +This has some handy properties. Inconsistencies in updating that state +will now appear as blockchain forks which catches a whole class of +programming errors. This also simplifies the development of secure +lightweight clients, as Merkle-hash proofs can be verified by checking +against the block hash, and that the block hash is signed by a quorum. + +There can be multiple ABCI socket connections to an application. +CometBFT creates three ABCI connections to the application; one +for the validation of transactions when broadcasting in the mempool, one +for the consensus engine to run block proposals, and one more for +querying the application state. + +It's probably evident that applications designers need to very carefully +design their message handlers to create a blockchain that does anything +useful but this architecture provides a place to start. The diagram +below illustrates the flow of messages via ABCI. + +![abci](../imgs/abci.png) + +## A Note on Determinism + +The logic for blockchain transaction processing must be deterministic. +If the application logic weren't deterministic, consensus would not be +reached among the CometBFT replica nodes. + +Solidity on Ethereum is a great language of choice for blockchain +applications because, among other reasons, it is a completely +deterministic programming language. However, it's also possible to +create deterministic applications using existing popular languages like +Java, C++, Python, or Go, by avoiding +sources of non-determinism such as: + +- random number generators (without deterministic seeding) +- race conditions on threads (or avoiding threads altogether) +- the system clock +- uninitialized memory (in unsafe programming languages like C + or C++) +- [floating point + arithmetic](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/) +- language features that are random (e.g. map iteration in Go) + +While programmers can avoid non-determinism by being careful, it is also +possible to create a special linter or static analyzer for each language +to check for determinism. In the future we may work with partners to +create such tools. + +## Consensus Overview + +CometBFT adopts [Tendermint consensus][tendermint-paper], +an easy-to-understand, mostly asynchronous, BFT consensus algorithm. +The algorithm follows a simple state machine that looks like this: + +![consensus-logic](../imgs/consensus_logic.png) + +Participants in the algorithm are called **validators**; they take turns +proposing blocks of transactions and voting on them. Blocks are +committed in a chain, with one block at each **height**. A block may +fail to be committed, in which case the algorithm moves to the next +**round**, and a new validator gets to propose a block for that height. +Two stages of voting are required to successfully commit a block; we +call them **pre-vote** and **pre-commit**. + +There is a picture of a couple doing the polka because validators are +doing something like a polka dance. When more than two-thirds of the +validators pre-vote for the same block, we call that a **polka**. Every +pre-commit must be justified by a polka in the same round. +A block is committed when +more than 2/3 of validators pre-commit for the same block in the same +round. + +Validators may fail to commit a block for a number of reasons; the +current proposer may be offline, or the network may be slow. Tendermint consensus +allows them to establish that a validator should be skipped. Validators +wait a small amount of time to receive a complete proposal block from +the proposer before voting to move to the next round. This reliance on a +timeout is what makes Tendermint consensus a weakly synchronous algorithm, rather +than an asynchronous one. However, the rest of the algorithm is +asynchronous, and validators only make progress after hearing from more +than two-thirds of the validator set. A simplifying element of +Tendermint consensus is that it uses the same mechanism to commit a block as it +does to skip to the next round. + +Assuming less than one-third of the validators are Byzantine, Tendermint consensus algorithm +guarantees that safety will never be violated - that is, validators will +never commit conflicting blocks at the same height. To do this it +introduces a few **locking** rules which modulate which paths can be +followed in the flow diagram. Once a validator precommits a block, it is +locked on that block. Then, + +1. it must prevote for the block it is locked on +2. it can only unlock, and precommit for a new block, if there is a + polka for that block in a later round + +## Stake + +In many systems, not all validators will have the same "weight" in the +consensus protocol. Thus, we are not so much interested in one-third or +two-thirds of the validators, but in those proportions of the total +voting power, which may not be uniformly distributed across individual +validators. + +Since CometBFT can replicate arbitrary applications, it is possible to +define a currency, and denominate the voting power in that currency. +When voting power is denominated in a native currency, the system is +often referred to as Proof-of-Stake. Validators can be forced, by logic +in the application, to "bond" their currency holdings in a security +deposit that can be destroyed if they're found to misbehave in the +consensus protocol. This adds an economic element to the security of the +protocol, allowing one to quantify the cost of violating the assumption +that less than one-third of voting power is Byzantine. + +The [Cosmos Network](https://cosmos.network) is designed to use this +Proof-of-Stake mechanism across an array of cryptocurrencies implemented +as ABCI applications. + +[tendermint-paper]: https://arxiv.org/abs/1807.04938 diff --git a/docs/introduction/what-is-cometbft.md b/docs/introduction/what-is-cometbft.md deleted file mode 100644 index abd98556faf..00000000000 --- a/docs/introduction/what-is-cometbft.md +++ /dev/null @@ -1,328 +0,0 @@ ---- -order: 4 ---- - -# What is CometBFT - -CometBFT is software for securely and consistently replicating an -application on many machines. By securely, we mean that CometBFT works -as long as less than 1/3 of machines fail in arbitrary ways. By consistently, -we mean that every non-faulty machine sees the same transaction log and -computes the same state. Secure and consistent replication is a -fundamental problem in distributed systems; it plays a critical role in -the fault tolerance of a broad range of applications, from currencies, -to elections, to infrastructure orchestration, and beyond. - -The ability to tolerate machines failing in arbitrary ways, including -becoming malicious, is known as Byzantine fault tolerance (BFT). The -theory of BFT is decades old, but software implementations have only -became popular recently, due largely to the success of "blockchain -technology" like Bitcoin and Ethereum. Blockchain technology is just a -reformalization of BFT in a more modern setting, with emphasis on -peer-to-peer networking and cryptographic authentication. The name -derives from the way transactions are batched in blocks, where each -block contains a cryptographic hash of the previous one, forming a -chain. - -CometBFT consists of two chief technical components: a blockchain -consensus engine and a generic application interface. -The consensus engine, -which is based on [Tendermint consensus algorithm][tendermint-paper], -ensures that the same transactions are -recorded on every machine in the same order. The application interface, -called the Application BlockChain Interface (ABCI), delivers the transactions -to applications for processing. Unlike other -blockchain and consensus solutions, which come pre-packaged with built -in state machines (like a fancy key-value store, or a quirky scripting -language), developers can use CometBFT for BFT state machine -replication of applications written in whatever programming language and -development environment is right for them. - -CometBFT is designed to be easy-to-use, simple-to-understand, highly -performant, and useful for a wide variety of distributed applications. - -## CometBFT vs. X - -CometBFT is broadly similar to two classes of software. The first -class consists of distributed key-value stores, like Zookeeper, etcd, -and consul, which use non-BFT consensus. The second class is known as -"blockchain technology", and consists of both cryptocurrencies like -Bitcoin and Ethereum, and alternative distributed ledger designs like -Hyperledger's Burrow. - -### Zookeeper, etcd, consul - -Zookeeper, etcd, and consul are all implementations of key-value stores -atop a classical, non-BFT consensus algorithm. Zookeeper uses an -algorithm called Zookeeper Atomic Broadcast, while etcd and consul use -the Raft log replication algorithm. A -typical cluster contains 3-5 machines, and can tolerate crash failures -in less than 1/2 of the machines (e.g., 1 out of 3 or 2 out of 5), -but even a single Byzantine fault can jeopardize the whole system. - -Each offering provides a slightly different implementation of a -featureful key-value store, but all are generally focused around -providing basic services to distributed systems, such as dynamic -configuration, service discovery, locking, leader-election, and so on. - -CometBFT is in essence similar software, but with two key differences: - -- It is Byzantine Fault Tolerant, meaning it can only tolerate less than 1/3 - of machines failing, but those failures can include arbitrary behavior - - including hacking and malicious attacks. -- It does not specify a - particular application, like a fancy key-value store. Instead, it - focuses on arbitrary state machine replication, so developers can build - the application logic that's right for them, from key-value store to - cryptocurrency to e-voting platform and beyond. - -### Bitcoin, Ethereum, etc - -[Tendermint consensus algorithm][tendermint-paper], adopted by CometBFT, -emerged in the tradition of cryptocurrencies like Bitcoin, -Ethereum, etc. with the goal of providing a more efficient and secure -consensus algorithm than Bitcoin's Proof of Work. In the early days, -Tendermint consensus-based blockchains had a simple currency built in, and to participate in -consensus, users had to "bond" units of the currency into a security -deposit which could be revoked if they misbehaved -this is what made -Tendermint consensus a Proof-of-Stake algorithm. - -Since then, CometBFT has evolved to be a general purpose blockchain -consensus engine that can host arbitrary application states. That means -it can be used as a plug-and-play replacement for the consensus engines -of other blockchain software. So one can take the current Ethereum code -base, whether in Rust, or Go, or Haskell, and run it as an ABCI -application using CometBFT. Indeed, [we did that with -Ethereum](https://github.com/cosmos/ethermint). And we plan to do -the same for Bitcoin, ZCash, and various other deterministic -applications as well. - -Another example of a cryptocurrency application built on CometBFT is -[the Cosmos network](http://cosmos.network). - -### Other Blockchain Projects - -[Fabric](https://github.com/hyperledger/fabric) takes a similar approach -to CometBFT, but is more opinionated about how the state is managed, -and requires that all application behavior runs in potentially many -docker containers, modules it calls "chaincode". It uses an -implementation of [PBFT](http://pmg.csail.mit.edu/papers/osdi99.pdf). -from a team at IBM that is [augmented to handle potentially -non-deterministic -chaincode](https://drops.dagstuhl.de/opus/volltexte/2017/7093/pdf/LIPIcs-OPODIS-2016-24.pdf). -It is possible to implement this docker-based behavior as an ABCI app in -CometBFT, though extending CometBFT to handle non-determinism -remains for future work. - -[Burrow](https://github.com/hyperledger/burrow) is an implementation of -the Ethereum Virtual Machine and Ethereum transaction mechanics, with -additional features for a name-registry, permissions, and native -contracts, and an alternative blockchain API. It uses CometBFT as its -consensus engine, and provides a particular application state. - -## ABCI Overview - -The [Application BlockChain Interface -(ABCI)](https://github.com/cometbft/cometbft/tree/main/abci) -allows for Byzantine Fault Tolerant replication of applications -written in any programming language. - -### Motivation - -Thus far, all blockchains "stacks" (such as -[Bitcoin](https://github.com/bitcoin/bitcoin)) have had a monolithic -design. That is, each blockchain stack is a single program that handles -all the concerns of a decentralized ledger; this includes P2P -connectivity, the "mempool" broadcasting of transactions, consensus on -the most recent block, account balances, Turing-complete contracts, -user-level permissions, etc. - -Using a monolithic architecture is typically bad practice in computer -science. It makes it difficult to reuse components of the code, and -attempts to do so result in complex maintenance procedures for forks of -the codebase. This is especially true when the codebase is not modular -in design and suffers from "spaghetti code". - -Another problem with monolithic design is that it limits you to the -language of the blockchain stack (or vice versa). In the case of -Ethereum which supports a Turing-complete bytecode virtual-machine, it -limits you to languages that compile down to that bytecode; while the -[list](https://github.com/pirapira/awesome-ethereum-virtual-machine#programming-languages-that-compile-into-evm) -is growing, it is still very limited. - -In contrast, our approach is to decouple the consensus engine and P2P -layers from the details of the state of the particular -blockchain application. We do this by abstracting away the details of -the application to an interface, which is implemented as a socket -protocol. - -### Intro to ABCI - -[CometBFT](https://github.com/cometbft/cometbft), the -"consensus engine", communicates with the application via a socket -protocol that satisfies the ABCI, the CometBFT Socket Protocol. - -To draw an analogy, let's talk about a well-known cryptocurrency, -Bitcoin. Bitcoin is a cryptocurrency blockchain where each node -maintains a fully audited Unspent Transaction Output (UTXO) database. If -one wanted to create a Bitcoin-like system on top of ABCI, CometBFT -would be responsible for - -- Sharing blocks and transactions between nodes -- Establishing a canonical/immutable order of transactions - (the blockchain) - -The application will be responsible for - -- Maintaining the UTXO database -- Validating cryptographic signatures of transactions -- Preventing transactions from spending non-existent transactions -- Allowing clients to query the UTXO database. - -CometBFT is able to decompose the blockchain design by offering a very -simple API (i.e. the ABCI) between the application process and consensus -process. - -The ABCI consists of 3 primary message types that get delivered from the -core to the application. The application replies with corresponding -response messages. - -The messages are specified here: [ABCI Message -Types](https://github.com/cometbft/cometbft/blob/main/proto/tendermint/abci/types.proto). - -The **DeliverTx** message is the work horse of the application. Each -transaction in the blockchain is delivered with this message. The -application needs to validate each transaction received with the -**DeliverTx** message against the current state, application protocol, -and the cryptographic credentials of the transaction. A validated -transaction then needs to update the application state — by binding a -value into a key values store, or by updating the UTXO database, for -instance. - -The **CheckTx** message is similar to **DeliverTx**, but it's only for -validating transactions. CometBFT's mempool first checks the -validity of a transaction with **CheckTx**, and only relays valid -transactions to its peers. For instance, an application may check an -incrementing sequence number in the transaction and return an error upon -**CheckTx** if the sequence number is old. Alternatively, they might use -a capabilities based system that requires capabilities to be renewed -with every transaction. - -The **Commit** message is used to compute a cryptographic commitment to -the current application state, to be placed into the next block header. -This has some handy properties. Inconsistencies in updating that state -will now appear as blockchain forks which catches a whole class of -programming errors. This also simplifies the development of secure -lightweight clients, as Merkle-hash proofs can be verified by checking -against the block hash, and that the block hash is signed by a quorum. - -There can be multiple ABCI socket connections to an application. -CometBFT creates three ABCI connections to the application; one -for the validation of transactions when broadcasting in the mempool, one -for the consensus engine to run block proposals, and one more for -querying the application state. - -It's probably evident that applications designers need to very carefully -design their message handlers to create a blockchain that does anything -useful but this architecture provides a place to start. The diagram -below illustrates the flow of messages via ABCI. - -![abci](../imgs/abci.png) - -## A Note on Determinism - -The logic for blockchain transaction processing must be deterministic. -If the application logic weren't deterministic, consensus would not be -reached among the CometBFT replica nodes. - -Solidity on Ethereum is a great language of choice for blockchain -applications because, among other reasons, it is a completely -deterministic programming language. However, it's also possible to -create deterministic applications using existing popular languages like -Java, C++, Python, or Go, by avoiding -sources of non-determinism such as: - -- random number generators (without deterministic seeding) -- race conditions on threads (or avoiding threads altogether) -- the system clock -- uninitialized memory (in unsafe programming languages like C - or C++) -- [floating point - arithmetic](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/) -- language features that are random (e.g. map iteration in Go) - -While programmers can avoid non-determinism by being careful, it is also -possible to create a special linter or static analyzer for each language -to check for determinism. In the future we may work with partners to -create such tools. - -## Consensus Overview - -CometBFT adopts [Tendermint consensus][tendermint-paper], -an easy-to-understand, mostly asynchronous, BFT consensus algorithm. -The algorithm follows a simple state machine that looks like this: - -![consensus-logic](../imgs/consensus_logic.png) - -Participants in the algorithm are called **validators**; they take turns -proposing blocks of transactions and voting on them. Blocks are -committed in a chain, with one block at each **height**. A block may -fail to be committed, in which case the algorithm moves to the next -**round**, and a new validator gets to propose a block for that height. -Two stages of voting are required to successfully commit a block; we -call them **pre-vote** and **pre-commit**. - -There is a picture of a couple doing the polka because validators are -doing something like a polka dance. When more than two-thirds of the -validators pre-vote for the same block, we call that a **polka**. Every -pre-commit must be justified by a polka in the same round. -A block is committed when -more than 2/3 of validators pre-commit for the same block in the same -round. - -Validators may fail to commit a block for a number of reasons; the -current proposer may be offline, or the network may be slow. Tendermint consensus -allows them to establish that a validator should be skipped. Validators -wait a small amount of time to receive a complete proposal block from -the proposer before voting to move to the next round. This reliance on a -timeout is what makes Tendermint consensus a weakly synchronous algorithm, rather -than an asynchronous one. However, the rest of the algorithm is -asynchronous, and validators only make progress after hearing from more -than two-thirds of the validator set. A simplifying element of -Tendermint consensus is that it uses the same mechanism to commit a block as it -does to skip to the next round. - -Assuming less than one-third of the validators are Byzantine, Tendermint consensus algorithm -guarantees that safety will never be violated - that is, validators will -never commit conflicting blocks at the same height. To do this it -introduces a few **locking** rules which modulate which paths can be -followed in the flow diagram. Once a validator precommits a block, it is -locked on that block. Then, - -1. it must prevote for the block it is locked on -2. it can only unlock, and precommit for a new block, if there is a - polka for that block in a later round - -## Stake - -In many systems, not all validators will have the same "weight" in the -consensus protocol. Thus, we are not so much interested in one-third or -two-thirds of the validators, but in those proportions of the total -voting power, which may not be uniformly distributed across individual -validators. - -Since CometBFT can replicate arbitrary applications, it is possible to -define a currency, and denominate the voting power in that currency. -When voting power is denominated in a native currency, the system is -often referred to as Proof-of-Stake. Validators can be forced, by logic -in the application, to "bond" their currency holdings in a security -deposit that can be destroyed if they're found to misbehave in the -consensus protocol. This adds an economic element to the security of the -protocol, allowing one to quantify the cost of violating the assumption -that less than one-third of voting power is Byzantine. - -The [Cosmos Network](https://cosmos.network) is designed to use this -Proof-of-Stake mechanism across an array of cryptocurrencies implemented -as ABCI applications. - -[tendermint-paper]: https://arxiv.org/abs/1807.04938 diff --git a/docs/qa/v034/README.md b/docs/qa/CometBFT-QA-34.md similarity index 76% rename from docs/qa/v034/README.md rename to docs/qa/CometBFT-QA-34.md index f3ac53e1d54..d633426407e 100644 --- a/docs/qa/v034/README.md +++ b/docs/qa/CometBFT-QA-34.md @@ -1,12 +1,14 @@ --- order: 1 parent: - title: CometBFT Quality Assurance Results for v0.34.x + title: CometBFT QA Results v0.34.x description: This is a report on the results obtained when running v0.34.x on testnets - order: 2 + order: 3 --- -# v0.34.x - From Tendermint Core to CometBFT +# CometBFT QA Results v0.34.x + +## v0.34.x - From Tendermint Core to CometBFT This section reports on the QA process we followed before releasing the first `v0.34.x` version from our CometBFT repository. @@ -54,7 +56,7 @@ Therefore we carry out a complete run of the _200-node test_ on the following ne ## Configuration and Results In the following sections we provide the results of the _200 node test_. -Each section reports the baseline results (for reference), the homogeneous network scenario (all CometBFT nodes), +Each section reports the baseline results (for reference), the homogeneous network scenario (all CometBFT nodes), and the mixed networks with 1/2, 1/3 and 2/3 of Tendermint Core nodes. ### Saturation Point @@ -62,10 +64,10 @@ and the mixed networks with 1/2, 1/3 and 2/3 of Tendermint Core nodes. As the CometBFT release candidate under test has minimal changes with respect to Tendermint Core `v0.34.26`, other than the rebranding changes, we can confidently reuse the results from the `v0.34.x` baseline test regarding -the [saturation point](./TMCore.md#finding-the-saturation-point). +the [saturation point](TMCore-QA-34.md#finding-the-saturation-point). Therefore, we will simply use a load of (`r=200,c=2`) -(see the explanation [here](./TMCore.md#finding-the-saturation-point)) on all experiments. +(see the explanation [here](TMCore-QA-34.md#finding-the-saturation-point)) on all experiments. We also include the baseline results for quick reference and comparison. @@ -87,26 +89,26 @@ We refer to these UUID to indicate to the representative runs. ### CometBFT Homogeneous network -![latencies](./img/homogeneous/all_experiments.png) +![latencies](img34/homogeneous/all_experiments.png) ### 1/2 Tendermint Core - 1/2 CometBFT -![latencies](./img/cmt1tm1/all_experiments.png) +![latencies](img34/cmt1tm1/all_experiments.png) ### 1/3 Tendermint Core - 2/3 CometBFT -![latencies](./img/cmt2tm1/all_experiments.png) +![latencies](img34/cmt2tm1/all_experiments.png) ### 2/3 Tendermint Core - 1/3 CometBFT -![latencies_all_tm2_3_cmt1_3](./img/v034_200node_tm2cmt1/all_experiments.png) +![latencies_all_tm2_3_cmt1_3](img34/v034_200node_tm2cmt1/all_experiments.png) ## Prometheus Metrics This section reports on the key Prometheus metrics extracted from the following experiments. -* Baseline results: `v0.34.x`, obtained in October 2022 and reported [here](./TMCore.md). +* Baseline results: `v0.34.x`, obtained in October 2022 and reported [here](TMCore-QA-34.md). * CometBFT homogeneous network: experiment with UUID starting with `be8c`. * Mixed network, 1/2 Tendermint Core `v0.34.26` and 1/2 running CometBFT: experiment with UUID starting with `04ee`. * Mixed network, 1/3 Tendermint Core `v0.34.26` and 2/3 running CometBFT: experiment with UUID starting with `fc5e`. @@ -125,35 +127,35 @@ The second one shows the evolution of the average over all full nodes. #### Baseline -![mempool-cumulative](./img/baseline/mempool_size.png) +![mempool-cumulative](img34/baseline/mempool_size.png) -![mempool-avg](./img/baseline/avg_mempool_size.png) +![mempool-avg](img34/baseline/avg_mempool_size.png) #### CometBFT Homogeneous network The results for the homogeneous network and the baseline are similar in terms of outstanding transactions. -![mempool-cumulative-homogeneous](./img/homogeneous/mempool_size.png) +![mempool-cumulative-homogeneous](img34/homogeneous/mempool_size.png) -![mempool-avg-homogeneous](./img/homogeneous/avg_mempool_size.png) +![mempool-avg-homogeneous](img34/homogeneous/avg_mempool_size.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![mempool size](./img/cmt1tm1/mempool_size.png) +![mempool size](img34/cmt1tm1/mempool_size.png) -![average mempool size](./img/cmt1tm1/avg_mempool_size.png) +![average mempool size](img34/cmt1tm1/avg_mempool_size.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![mempool size](./img/cmt2tm1/mempool_size.png) +![mempool size](img34/cmt2tm1/mempool_size.png) -![average mempool size](./img/cmt2tm1/avg_mempool_size.png) +![average mempool size](img34/cmt2tm1/avg_mempool_size.png) #### 2/3 Tendermint Core - 1/3 CometBFT -![mempool_tm2_3_cmt_1_3](./img/v034_200node_tm2cmt1/mempool_size.png) +![mempool_tm2_3_cmt_1_3](img34/v034_200node_tm2cmt1/mempool_size.png) -![mempool-avg_tm2_3_cmt_1_3](./img/v034_200node_tm2cmt1/avg_mempool_size.png) +![mempool-avg_tm2_3_cmt_1_3](img34/v034_200node_tm2cmt1/avg_mempool_size.png) ### Consensus Rounds per Height @@ -161,10 +163,10 @@ The following graphs show the rounds needed to complete each height and agree on A value of `0` shows that only one round was required (with id `0`), and a value of `1` shows that two rounds were required. -#### Baseline +#### Baseline We can see that round 1 is reached with a certain frequency. -![rounds](./img/baseline/rounds.png) +![rounds](img34/baseline/rounds.png) #### CometBFT Homogeneous network @@ -173,19 +175,19 @@ and a few nodes even needed to advance to round 2 at one point. This coincides with the time at which we observed the biggest peak in mempool size on the corresponding plot, shown above. -![rounds-homogeneous](./img/homogeneous/rounds.png) +![rounds-homogeneous](img34/homogeneous/rounds.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![peers](./img/cmt1tm1/rounds.png) +![peers](img34/cmt1tm1/rounds.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![peers](./img/cmt2tm1/rounds.png) +![peers](img34/cmt2tm1/rounds.png) #### 2/3 Tendermint Core - 1/3 CometBFT -![rounds-tm2_3_cmt1_3](./img/v034_200node_tm2cmt1/rounds.png) +![rounds-tm2_3_cmt1_3](img34/v034_200node_tm2cmt1/rounds.png) ### Peers @@ -200,30 +202,30 @@ Seed nodes typically have a higher number of peers. The fact that non-seed nodes reach more than 50 peers is due to [#9548](https://github.com/tendermint/tendermint/issues/9548). -![peers](./img/baseline/peers.png) +![peers](img34/baseline/peers.png) #### CometBFT Homogeneous network -The results for the homogeneous network are very similar to the baseline. +The results for the homogeneous network are very similar to the baseline. The only difference being that the seed nodes seem to loose peers in the middle of the experiment. However this cannot be attributed to the differences in the code, which are mainly rebranding. -![peers-homogeneous](./img/homogeneous/peers.png) +![peers-homogeneous](img34/homogeneous/peers.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![peers](./img/cmt1tm1/peers.png) +![peers](img34/cmt1tm1/peers.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![peers](./img/cmt2tm1/peers.png) +![peers](img34/cmt2tm1/peers.png) #### 2/3 Tendermint Core - 1/3 CometBFT As in the homogeneous case, there is some variation in the number of peers for some nodes. These, however, do not affect the average. -![peers-tm2_3_cmt1_3](./img/v034_200node_tm2cmt1/peers.png) +![peers-tm2_3_cmt1_3](img34/v034_200node_tm2cmt1/peers.png) ### Blocks Produced per Minute, Transactions Processed per Minute @@ -236,11 +238,11 @@ The thick red dashed line show the rates' moving averages. The average number of blocks/minute oscilate between 10 and 40. -![heights](./img/baseline/block_rate_regular.png) +![heights](img34/baseline/block_rate_regular.png) The number of transactions/minute tops around 30k. -![total-txs](./img/baseline/total_txs_rate_regular.png) +![total-txs](img34/baseline/total_txs_rate_regular.png) #### CometBFT Homogeneous network @@ -248,30 +250,30 @@ The number of transactions/minute tops around 30k. The plot showing the block production rate shows that the rate oscillates around 20 blocks/minute, mostly within the same range as the baseline. -![heights-homogeneous-rate](./img/homogeneous/block_rate_regular.png) +![heights-homogeneous-rate](img34/homogeneous/block_rate_regular.png) -The plot showing the transaction rate shows the rate stays around 20000 transactions per minute, +The plot showing the transaction rate shows the rate stays around 20000 transactions per minute, also topping around 30k. -![txs-homogeneous-rate](./img/homogeneous/total_txs_rate_regular.png) +![txs-homogeneous-rate](img34/homogeneous/total_txs_rate_regular.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![height rate](./img/cmt1tm1/block_rate_regular.png) +![height rate](img34/cmt1tm1/block_rate_regular.png) -![transaction rate](./img/cmt1tm1/total_txs_rate_regular.png) +![transaction rate](img34/cmt1tm1/total_txs_rate_regular.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![height rate](./img/cmt2tm1/block_rate_regular.png) +![height rate](img34/cmt2tm1/block_rate_regular.png) -![transaction rate](./img/cmt2tm1/total_txs_rate_regular.png) +![transaction rate](img34/cmt2tm1/total_txs_rate_regular.png) #### 2/3 Tendermint Core - 1/3 CometBFT -![height rate](./img/v034_200node_tm2cmt1/block_rate_regular.png) +![height rate](img34/v034_200node_tm2cmt1/block_rate_regular.png) -![transaction rate](./img/v034_200node_tm2cmt1/total_txs_rate_regular.png) +![transaction rate](img34/v034_200node_tm2cmt1/total_txs_rate_regular.png) ### Memory Resident Set Size @@ -279,83 +281,83 @@ The following graphs show the Resident Set Size (RSS) of all monitored processes #### Baseline -![rss](./img/baseline/memory.png) +![rss](img34/baseline/memory.png) -![rss-avg](./img/baseline/avg_memory.png) +![rss-avg](img34/baseline/avg_memory.png) #### CometBFT Homogeneous network This is the plot for the homogeneous network, which is slightly more stable than the baseline over the time of the experiment. -![rss-homogeneous](./img/homogeneous/memory.png) +![rss-homogeneous](img34/homogeneous/memory.png) And this is the average plot. It oscillates around 560 MiB, which is noticeably lower than the baseline. -![rss-avg-homogeneous](./img/homogeneous/avg_memory.png) +![rss-avg-homogeneous](img34/homogeneous/avg_memory.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![rss](./img/cmt1tm1/memory.png) +![rss](img34/cmt1tm1/memory.png) -![rss average](./img/cmt1tm1/avg_memory.png) +![rss average](img34/cmt1tm1/avg_memory.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![rss](./img/cmt2tm1/memory.png) +![rss](img34/cmt2tm1/memory.png) -![rss average](./img/cmt2tm1/avg_memory.png) +![rss average](img34/cmt2tm1/avg_memory.png) #### 2/3 Tendermint Core - 1/3 CometBFT -![rss](./img/v034_200node_tm2cmt1/memory.png) +![rss](img34/v034_200node_tm2cmt1/memory.png) -![rss average](./img/v034_200node_tm2cmt1/avg_memory.png) +![rss average](img34/v034_200node_tm2cmt1/avg_memory.png) ### CPU utilization -The following graphs show the `load1` of nodes, as typically shown in the first line of the Unix `top` +The following graphs show the `load1` of nodes, as typically shown in the first line of the Unix `top` command, and their average value. #### Baseline -![load1](./img/baseline/cpu.png) +![load1](img34/baseline/cpu.png) -![load1-avg](./img/baseline/avg_cpu.png) +![load1-avg](img34/baseline/avg_cpu.png) #### CometBFT Homogeneous network The load in the homogenous network is, similarly to the baseline case, below 5 and, therefore, normal. -![load1-homogeneous](./img/homogeneous/cpu.png) +![load1-homogeneous](img34/homogeneous/cpu.png) As expected, the average plot also looks similar. -![load1-homogeneous-avg](./img/homogeneous/avg_cpu.png) +![load1-homogeneous-avg](img34/homogeneous/avg_cpu.png) #### 1/2 Tendermint Core - 1/2 CometBFT -![load1](./img/cmt1tm1/cpu.png) +![load1](img34/cmt1tm1/cpu.png) -![average load1](./img/cmt1tm1/avg_cpu.png) +![average load1](img34/cmt1tm1/avg_cpu.png) #### 1/3 Tendermint Core - 2/3 CometBFT -![load1](./img/cmt2tm1/cpu.png) +![load1](img34/cmt2tm1/cpu.png) -![average load1](./img/cmt2tm1/avg_cpu.png) +![average load1](img34/cmt2tm1/avg_cpu.png) #### 2/3 Tendermint Core - 1/3 CometBFT -![load1](./img/v034_200node_tm2cmt1/cpu.png) +![load1](img34/v034_200node_tm2cmt1/cpu.png) -![average load1](./img/v034_200node_tm2cmt1/avg_cpu.png) +![average load1](img34/v034_200node_tm2cmt1/avg_cpu.png) ## Test Results The comparison of the baseline results and the homogeneous case show that both scenarios had similar numbers and are therefore equivalent. -The mixed nodes cases show that networks operate normally with a mix of compatible Tendermint Core and CometBFT versions. +The mixed nodes cases show that networks operate normally with a mix of compatible Tendermint Core and CometBFT versions. Although not the main goal, a comparison of metric numbers with the homogenous case and the baseline scenarios show similar results and therefore we can conclude that mixing compatible Tendermint Core and CometBFT introduces not performance degradation. A conclusion of these tests is shown in the following table, along with the commit versions used in the experiments. diff --git a/docs/qa/v037/CometBFT.md b/docs/qa/CometBFT-QA-37.md similarity index 78% rename from docs/qa/v037/CometBFT.md rename to docs/qa/CometBFT-QA-37.md index 0095a3be95a..1717ecf3ecd 100644 --- a/docs/qa/v037/CometBFT.md +++ b/docs/qa/CometBFT-QA-37.md @@ -1,14 +1,14 @@ --- order: 1 parent: - title: CometBFT Quality Assurance Results for v0.37.x + title: CometBFT QA Results v0.37.x description: This is a report on the results obtained when running CometBFT v0.37.x on testnets - order: 2 + order: 5 --- -# v0.37.x +# CometBFT QA Results v0.37.x -This iteration of the QA was run on CometBFT `v0.37.0-alpha3`, the first `v0.37.x` version from the CometBFT repository. +This iteration of the QA was run on CometBFT `v0.37.0-alpha3`, the first `v0.37.x` version from the CometBFT repository. The changes with respect to the baseline, `TM v0.37.x` as of Oct 12, 2022 (Commit: 1cf9d8e276afe8595cba960b51cd056514965fd1), include the rebranding of our fork of Tendermint Core to CometBFT and several improvements, described in the CometBFT [CHANGELOG](https://github.com/cometbft/cometbft/blob/v0.37.0-alpha.3/CHANGELOG.md). @@ -19,7 +19,7 @@ As in other iterations of our QA process, we have used a 200-node network as tes ### Saturation point As in previous iterations, in our QA experiments, the system is subjected to a load slightly under a saturation point. -The method to identify the saturation point is explained [here](../v034/README.md#finding-the-saturation-point) and its application to the baseline is described [here](./TMCore.md#finding-the-saturation-point). +The method to identify the saturation point is explained [here](CometBFT-QA-34.md#finding-the-saturation-point) and its application to the baseline is described [here](TMCore-QA-37.md#finding-the-saturation-point). We use the same saturation point, that is, `c`, the number of connections created by the load runner process to the target node, is 2 and `r`, the rate or number of transactions issued per second, is 200. ## Examining latencies @@ -27,17 +27,17 @@ We use the same saturation point, that is, `c`, the number of connections create The following figure plots six experiments carried out with the network. Unique identifiers, UUID, for each execution are presented on top of each graph. -![latencies](./img/200nodes_cmt037/all_experiments.png) +![latencies](img37/200nodes_cmt037/all_experiments.png) We can see that the latencies follow comparable patterns across all experiments. Therefore, in the following sections we will only present the results for one representative run, chosen randomly, with UUID starting with `75cb89a8`. -![latencies](./img/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png). +![latencies](img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png). For reference, the following figure shows the latencies of different configuration of the baseline. `c=02 r=200` corresponds to the same configuration as in this experiment. -![all-latencies](./img/200nodes_tm037/v037_200node_latencies.png) +![all-latencies](img37/200nodes_tm037/v037_200node_latencies.png) As can be seen, latencies are similar. @@ -47,24 +47,24 @@ This section further examines key metrics for this experiment extracted from Pro ### Mempool Size -The mempool size, a count of the number of transactions in the mempool, was shown to be stable and homogeneous at all full nodes. +The mempool size, a count of the number of transactions in the mempool, was shown to be stable and homogeneous at all full nodes. It did not exhibit any unconstrained growth. The plot below shows the evolution over time of the cumulative number of transactions inside all full nodes' mempools at a given time. -![mempoool-cumulative](./img/200nodes_cmt037/mempool_size.png) +![mempoool-cumulative](img37/200nodes_cmt037/mempool_size.png) The following picture shows the evolution of the average mempool size over all full nodes, which mostly oscilates between 1500 and 2000 outstanding transactions. -![mempool-avg](./img/200nodes_cmt037/avg_mempool_size.png) +![mempool-avg](img37/200nodes_cmt037/avg_mempool_size.png) The peaks observed coincide with the moments when some nodes reached round 1 of consensus (see below). The behavior is similar to the observed in the baseline, presented next. -![mempool-cumulative-baseline](./img/200nodes_tm037/mempool_size.png) +![mempool-cumulative-baseline](img37/200nodes_tm037/mempool_size.png) -![mempool-avg-baseline](./img/200nodes_tm037/avg_mempool_size.png) +![mempool-avg-baseline](img37/200nodes_tm037/avg_mempool_size.png) ### Peers @@ -73,29 +73,29 @@ The number of peers was stable at all nodes. It was higher for the seed nodes (around 140) than for the rest (between 16 and 78). The red dashed line denotes the average value. -![peers](./img/200nodes_cmt037/peers.png) +![peers](img37/200nodes_cmt037/peers.png) Just as in the baseline, shown next, the fact that non-seed nodes reach more than 50 peers is due to [\#9548]. -![peers](./img/200nodes_tm037/peers.png) +![peers](img37/200nodes_tm037/peers.png) ### Consensus Rounds per Height Most heights took just one round, that is, round 0, but some nodes needed to advance to round 1 and eventually round 2. -![rounds](./img/200nodes_cmt037/rounds.png) +![rounds](img37/200nodes_cmt037/rounds.png) The following specific run of the baseline presented better results, only requiring up to round 1, but reaching higher rounds is not uncommon in the corresponding software version. -![rounds](./img/200nodes_tm037/rounds.png) +![rounds](img37/200nodes_tm037/rounds.png) ### Blocks Produced per Minute, Transactions Processed per Minute -The following plot shows the rate in which blocks were created, from the point of view of each node. +The following plot shows the rate in which blocks were created, from the point of view of each node. That is, it shows when each node learned that a new block had been agreed upon. -![heights](./img/200nodes_cmt037/block_rate.png) +![heights](img37/200nodes_cmt037/block_rate.png) For most of the time when load was being applied to the system, most of the nodes stayed around 20 to 25 blocks/minute. @@ -104,26 +104,26 @@ The spike to more than 175 blocks/minute is due to a slow node catching up. The collective spike on the right of the graph marks the end of the load injection, when blocks become smaller (empty) and impose less strain on the network. This behavior is reflected in the following graph, which shows the number of transactions processed per minute. -![total-txs](./img/200nodes_cmt037/total_txs_rate.png) +![total-txs](img37/200nodes_cmt037/total_txs_rate.png) The baseline experienced a similar behavior, shown in the following two graphs. The first depicts the block rate. -![heights-baseline](./img/200nodes_tm037/block_rate_regular.png) +![heights-baseline](img37/200nodes_tm037/block_rate_regular.png) The second plots the transaction rate. -![total-txs-baseline](./img/200nodes_tm037/total_txs_rate_regular.png) +![total-txs-baseline](img37/200nodes_tm037/total_txs_rate_regular.png) ### Memory Resident Set Size The Resident Set Size of all monitored processes is plotted below, with maximum memory usage of 2GB. -![rss](./img/200nodes_cmt037/memory.png) +![rss](img37/200nodes_cmt037/memory.png) A similar behavior was shown in the baseline, presented next. -![rss](./img/200nodes_tm037/memory.png) +![rss](img37/200nodes_tm037/memory.png) The memory of all processes went down as the load as removed, showing no signs of unconstrained growth. @@ -136,11 +136,11 @@ as it usually appears in the It is contained below 5 on most nodes, as seen in the following graph. -![load1](./img/200nodes_cmt037/cpu.png) +![load1](img37/200nodes_cmt037/cpu.png) A similar behavior was seen in the baseline. -![load1-baseline](./img/200nodes_tm037/cpu.png) +![load1-baseline](img37/200nodes_tm037/cpu.png) ## Test Results @@ -154,4 +154,4 @@ A conclusion of these tests is shown in the following table, along with the comm |CometBFT | 2023-02-14 | v0.37.0-alpha3 (bef9a830e7ea7da30fa48f2cc236b1f465cc5833) | Pass -[\#9548]: https://github.com/tendermint/tendermint/issues/9548 \ No newline at end of file +[\#9548]: https://github.com/tendermint/tendermint/issues/9548 diff --git a/docs/qa/README.md b/docs/qa/README.md index 76341598eb2..d59049074bc 100644 --- a/docs/qa/README.md +++ b/docs/qa/README.md @@ -19,7 +19,7 @@ used to decide if a release is passing the Quality Assurance process. The results obtained in each release are stored in their own directory. The following releases have undergone the Quality Assurance process, and the corresponding reports include detailed information on tests and comparison with the baseline. -* [TM v0.34.x](./v034/TMCore.md) - Tested prior to releasing Tendermint Core v0.34.22. -* [v0.34.x](./v034/CometBFT.md) - Tested prior to releasing v0.34.27, using TM v0.34.x results as baseline. -* [TM v0.37.x](./v037/TMCore.md) - Tested prior to releasing TM v0.37.x, using TM v0.34.x results as baseline. -* [v0.37.x](./v037/CometBFT.md) - Tested on CometBFT v0.37.0-alpha3, using TM v0.37.x results as baseline. +* [TM v0.34.x](TMCore-QA-34.md) - Tested prior to releasing Tendermint Core v0.34.22. +* [v0.34.x](CometBFT-QA-34.md) - Tested prior to releasing v0.34.27, using TM v0.34.x results as baseline. +* [TM v0.37.x](TMCore-QA-37.md) - Tested prior to releasing TM v0.37.x, using TM v0.34.x results as baseline. +* [v0.37.x](CometBFT-QA-37.md) - Tested on CometBFT v0.37.0-alpha3, using TM v0.37.x results as baseline. diff --git a/docs/qa/v034/TMCore.md b/docs/qa/TMCore-QA-34.md similarity index 88% rename from docs/qa/v034/TMCore.md rename to docs/qa/TMCore-QA-34.md index 5fc1225d978..e5764611c06 100644 --- a/docs/qa/v034/TMCore.md +++ b/docs/qa/TMCore-QA-34.md @@ -1,12 +1,12 @@ --- order: 1 parent: - title: Tendermint Core Quality Assurance Results for v0.34.x + title: Tendermint Core QA Results v0.34.x description: This is a report on the results obtained when running v0.34.x on testnets order: 2 --- -# Tendermint Core v0.34.x +# Tendermint Core QA Results v0.34.x ## 200 Node Testnet @@ -18,7 +18,7 @@ from being stable: the load runner tries to produce slightly more transactions t be processed by the testnet. The following table summarizes the results for v0.34.x, for the different experiments -(extracted from file [`v034_report_tabbed.txt`](./img/v034_report_tabbed.txt)). +(extracted from file [`v034_report_tabbed.txt`](img34/v034_report_tabbed.txt)). The X axis of this table is `c`, the number of connections created by the load runner process to the target node. The Y axis of this table is `r`, the rate or number of transactions issued per second. @@ -57,14 +57,14 @@ in order to further study the performance of this release. This is a plot of the CPU load (average over 1 minute, as output by `top`) of the load runner for (`r=200,c=2`), where we can see that the load stays close to 0 most of the time. -![load-load-runner](./img/v034_r200c2_load-runner.png) +![load-load-runner](img34/v034_r200c2_load-runner.png) ### Examining latencies -The method described [here](../method.md) allows us to plot the latencies of transactions +The method described [here](method.md) allows us to plot the latencies of transactions for all experiments. -![all-latencies](./img/v034_200node_latencies.png) +![all-latencies](img34/v034_200node_latencies.png) As we can see, even the experiments beyond the saturation diagonal managed to keep transaction latency stable (i.e. not constantly increasing). @@ -84,7 +84,7 @@ This is a visual effect of the plot; what appear to be points in the plot are ac clusters of points. To corroborate this, we have zoomed in the plot above by setting (carefully chosen) tiny axis intervals. The cluster shown below looks like a single point in the plot above. -![all-latencies-zoomed](./img/v034_200node_latencies_zoomed.png) +![all-latencies-zoomed](img34/v034_200node_latencies_zoomed.png) The plot of latencies can we used as a baseline to compare with other releases. @@ -92,7 +92,7 @@ The following plot summarizes average latencies versus overall throughput across different numbers of WebSocket connections to the node into which transactions are being loaded. -![latency-vs-throughput](./img/v034_latency_throughput.png) +![latency-vs-throughput](img34/v034_latency_throughput.png) ### Prometheus Metrics on the Chosen Experiment @@ -108,12 +108,12 @@ at a given time. The two spikes that can be observed correspond to a period where consensus instances proceeded beyond the initial round at some nodes. -![mempool-cumulative](./img/v034_r200c2_mempool_size.png) +![mempool-cumulative](img34/v034_r200c2_mempool_size.png) The plot below shows evolution of the average over all full nodes, which oscillates between 1500 and 2000 outstanding transactions. -![mempool-avg](./img/v034_r200c2_mempool_size_avg.png) +![mempool-avg](img34/v034_r200c2_mempool_size_avg.png) The peaks observed coincide with the moments when some nodes proceeded beyond the initial round of consensus (see below). @@ -123,26 +123,26 @@ The number of peers was stable at all nodes. It was higher for the seed nodes (around 140) than for the rest (between 21 and 74). The fact that non-seed nodes reach more than 50 peers is due to #9548. -![peers](./img/v034_r200c2_peers.png) +![peers](img34/v034_r200c2_peers.png) #### Consensus Rounds per Height Most nodes used only round 0 for most heights, but some nodes needed to advance to round 1 for some heights. -![rounds](./img/v034_r200c2_rounds.png) +![rounds](img34/v034_r200c2_rounds.png) #### Blocks Produced per Minute, Transactions Processed per Minute The blocks produced per minute are the slope of this plot. -![heights](./img/v034_r200c2_heights.png) +![heights](img34/v034_r200c2_heights.png) Over a period of 2 minutes, the height goes from 530 to 569. This results in an average of 19.5 blocks produced per minute. The transactions processed per minute are the slope of this plot. -![total-txs](./img/v034_r200c2_total-txs.png) +![total-txs](img34/v034_r200c2_total-txs.png) Over a period of 2 minutes, the total goes from 64525 to 100125 transactions, resulting in 17800 transactions per minute. However, we can see in the plot that @@ -154,11 +154,11 @@ we obtain 20343 transactions per minute. Resident Set Size of all monitored processes is plotted below. -![rss](./img/v034_r200c2_rss.png) +![rss](img34/v034_r200c2_rss.png) The average over all processes oscillates around 1.2 GiB and does not demonstrate unconstrained growth. -![rss-avg](./img/v034_r200c2_rss_avg.png) +![rss-avg](img34/v034_r200c2_rss_avg.png) #### CPU utilization @@ -166,7 +166,7 @@ The best metric from Prometheus to gauge CPU utilization in a Unix machine is `l as it usually appears in the [output of `top`](https://www.digitalocean.com/community/tutorials/load-average-in-linux). -![load1](./img/v034_r200c2_load1.png) +![load1](img34/v034_r200c2_load1.png) It is contained in most cases below 5, which is generally considered acceptable load. @@ -191,7 +191,7 @@ we are focusing on here. The plot of all latencies can be seen in the following plot. -![rotating-all-latencies](./img/v034_rotating_latencies.png) +![rotating-all-latencies](img34/v034_rotating_latencies.png) We can observe there are some very high latencies, towards the end of the test. Upon suspicion that they are duplicate transactions, we examined the latencies @@ -200,7 +200,7 @@ raw file and discovered there are more than 100K duplicate transactions. The following plot shows the latencies file where all duplicate transactions have been removed, i.e., only the first occurrence of a duplicate transaction is kept. -![rotating-all-latencies-uniq](./img/v034_rotating_latencies_uniq.png) +![rotating-all-latencies-uniq](img34/v034_rotating_latencies_uniq.png) This problem, existing in `v0.34.x`, will need to be addressed, perhaps in the same way we addressed it when running the 200 node test with high loads: increasing the `cache_size` @@ -215,7 +215,7 @@ We are only interested in those for which the catch-up process (blocksync) may h Just as shown for the 200 node test, the blocks produced per minute are the gradient of this plot. -![rotating-heights](./img/v034_rotating_heights.png) +![rotating-heights](img34/v034_rotating_heights.png) Over a period of 5229 seconds, the height goes from 2 to 3638. This results in an average of 41 blocks produced per minute. @@ -225,11 +225,11 @@ The following plot shows only the heights reported by ephemeral nodes is only showed _once the node has switched to consensus_, hence the gaps when nodes are killed, wiped out, started from scratch, and catching up. -![rotating-heights-ephe](./img/v034_rotating_heights_ephe.png) +![rotating-heights-ephe](img34/v034_rotating_heights_ephe.png) The transactions processed per minute are the gradient of this plot. -![rotating-total-txs](./img/v034_rotating_total-txs.png) +![rotating-total-txs](img34/v034_rotating_total-txs.png) The small lines we see periodically close to `y=0` are the transactions that ephemeral nodes start processing when they are caught up. @@ -244,7 +244,7 @@ The plot below shows the evolution in peers throughout the experiment. The periodic changes observed are due to the ephemeral nodes being stopped, wiped out, and recreated. -![rotating-peers](./img/v034_rotating_peers.png) +![rotating-peers](img34/v034_rotating_peers.png) The validators' plots are concentrated at the higher part of the graph, whereas the ephemeral nodes are mostly at the lower part. @@ -254,7 +254,7 @@ are mostly at the lower part. The average Resident Set Size (RSS) over all processes seems stable, and slightly growing toward the end. This might be related to the increased in transaction load observed above. -![rotating-rss-avg](./img/v034_rotating_rss_avg.png) +![rotating-rss-avg](img34/v034_rotating_rss_avg.png) The memory taken by the validators and the ephemeral nodes (when they are up) is comparable. @@ -262,7 +262,7 @@ The memory taken by the validators and the ephemeral nodes (when they are up) is The plot shows metric `load1` for all nodes. -![rotating-load1](./img/v034_rotating_load1.png) +![rotating-load1](img34/v034_rotating_load1.png) It is contained under 5 most of the time, which is considered normal load. The purple line, which follows a different pattern is the validator receiving all diff --git a/docs/qa/v037/TMCore.md b/docs/qa/TMCore-QA-37.md similarity index 77% rename from docs/qa/v037/TMCore.md rename to docs/qa/TMCore-QA-37.md index 6797d2144c4..edff57b0276 100644 --- a/docs/qa/v037/TMCore.md +++ b/docs/qa/TMCore-QA-37.md @@ -1,12 +1,12 @@ --- order: 1 parent: - title: CometBFT Quality Assurance Results for v0.37.x + title: Tendermint Core QA Results v0.37.x description: This is a report on the results obtained when running TM v0.37.x on testnets - order: 2 + order: 4 --- -# v0.37.x +# Tendermint Core QA Results v0.37.x ## Issues discovered @@ -32,11 +32,11 @@ During this iteration of the QA process, the following issues were found: ### Finding the Saturation Point The first goal is to identify the saturation point and compare it with the baseline (v0.34.x). -For further details, see [this paragraph](../v034/README.md#finding-the-saturation-point) +For further details, see [this paragraph](CometBFT-QA-34.md#finding-the-saturation-point) in the baseline version. The following table summarizes the results for v0.37.x, for the different experiments -(extracted from file [`v037_report_tabbed.txt`](./img/200nodes_tm037/v037_report_tabbed.txt)). +(extracted from file [`v037_report_tabbed.txt`](img37/200nodes_tm037/v037_report_tabbed.txt)). The X axis of this table is `c`, the number of connections created by the load runner process to the target node. The Y axis of this table is `r`, the rate or number of transactions issued per second. @@ -63,7 +63,7 @@ The saturation point is beyond the diagonal: * `r=100,c=4` which is at the same place as the baseline. For more details on the saturation point, see -[this paragraph](../v034/README.md#finding-the-saturation-point) in the baseline version. +[this paragraph](CometBFT-QA-34.md#finding-the-saturation-point) in the baseline version. The experiment chosen to examine Prometheus metrics is the same as in the baseline: **`r=200,c=2`**. @@ -72,27 +72,27 @@ The load runner's CPU load was negligible (near 0) when running `r=200,c=2`. ### Examining latencies -The method described [here](../method.md) allows us to plot the latencies of transactions +The method described [here](method.md) allows us to plot the latencies of transactions for all experiments. -![all-latencies](./img/200nodes_tm037/v037_200node_latencies.png) +![all-latencies](img37/200nodes_tm037/v037_200node_latencies.png) The data seen in the plot is similar to that of the baseline. -![all-latencies-bl](../v034/img/v034_200node_latencies.png) +![all-latencies-bl](img34/v034_200node_latencies.png) Therefore, for further details on these plots, -see [this paragraph](../v034/README.md#examining-latencies) in the baseline version. +see [this paragraph](CometBFT-QA-34.md#examining-latencies) in the baseline version. The following plot summarizes average latencies versus overall throughputs across different numbers of WebSocket connections to the node into which transactions are being loaded. -![latency-vs-throughput](./img/200nodes_tm037/v037_latency_throughput.png) +![latency-vs-throughput](img37/200nodes_tm037/v037_latency_throughput.png) This is similar to that of the baseline plot: -![latency-vs-throughput-bl](../v034/img/v034_latency_throughput.png) +![latency-vs-throughput-bl](img34/v034_latency_throughput.png) ### Prometheus Metrics on the Chosen Experiment @@ -106,55 +106,55 @@ at all full nodes. It did not exhibit any unconstrained growth. The plot below shows the evolution over time of the cumulative number of transactions inside all full nodes' mempools at a given time. -![mempool-cumulative](./img/200nodes_tm037/v037_r200c2_mempool_size.png) +![mempool-cumulative](img37/200nodes_tm037/v037_r200c2_mempool_size.png) The plot below shows evolution of the average over all full nodes, which oscillate between 1500 and 2000 outstanding transactions. -![mempool-avg](./img/200nodes_tm037/v037_r200c2_mempool_size_avg.png) +![mempool-avg](img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png) The peaks observed coincide with the moments when some nodes reached round 1 of consensus (see below). **These plots yield similar results to the baseline**: -![mempool-cumulative-bl](../v034/img/v034_r200c2_mempool_size.png) +![mempool-cumulative-bl](img34/v034_r200c2_mempool_size.png) -![mempool-avg-bl](../v034/img/v034_r200c2_mempool_size_avg.png) +![mempool-avg-bl](img34/v034_r200c2_mempool_size_avg.png) #### Peers The number of peers was stable at all nodes. It was higher for the seed nodes (around 140) than for the rest (between 16 and 78). -![peers](./img/200nodes_tm037/v037_r200c2_peers.png) +![peers](img37/200nodes_tm037/v037_r200c2_peers.png) Just as in the baseline, the fact that non-seed nodes reach more than 50 peers is due to #9548. **This plot yields similar results to the baseline**: -![peers-bl](../v034/img/v034_r200c2_peers.png) +![peers-bl](img34/v034_r200c2_peers.png) #### Consensus Rounds per Height Most heights took just one round, but some nodes needed to advance to round 1 at some point. -![rounds](./img/200nodes_tm037/v037_r200c2_rounds.png) +![rounds](img37/200nodes_tm037/v037_r200c2_rounds.png) **This plot yields slightly better results than the baseline**: -![rounds-bl](../v034/img/v034_r200c2_rounds.png) +![rounds-bl](img34/v034_r200c2_rounds.png) #### Blocks Produced per Minute, Transactions Processed per Minute The blocks produced per minute are the gradient of this plot. -![heights](./img/200nodes_tm037/v037_r200c2_heights.png) +![heights](img37/200nodes_tm037/v037_r200c2_heights.png) Over a period of 2 minutes, the height goes from 477 to 524. This results in an average of 23.5 blocks produced per minute. The transactions processed per minute are the gradient of this plot. -![total-txs](./img/200nodes_tm037/v037_r200c2_total-txs.png) +![total-txs](img37/200nodes_tm037/v037_r200c2_total-txs.png) Over a period of 2 minutes, the total goes from 64525 to 100125 transactions, resulting in 17800 transactions per minute. However, we can see in the plot that @@ -164,25 +164,25 @@ we obtain 23733 transactions per minute. **These plots yield similar results to the baseline**: -![heights-bl](../v034/img/v034_r200c2_heights.png) +![heights-bl](img34/v034_r200c2_heights.png) -![total-txs](../v034/img/v034_r200c2_total-txs.png) +![total-txs](img34/v034_r200c2_total-txs.png) #### Memory Resident Set Size Resident Set Size of all monitored processes is plotted below. -![rss](./img/200nodes_tm037/v037_r200c2_rss.png) +![rss](img37/200nodes_tm037/v037_r200c2_rss.png) The average over all processes oscillates around 380 MiB and does not demonstrate unconstrained growth. -![rss-avg](./img/200nodes_tm037/v037_r200c2_rss_avg.png) +![rss-avg](img37/200nodes_tm037/v037_r200c2_rss_avg.png) **These plots yield similar results to the baseline**: -![rss-bl](../v034/img/v034_r200c2_rss.png) +![rss-bl](img34/v034_r200c2_rss.png) -![rss-avg-bl](../v034/img/v034_r200c2_rss_avg.png) +![rss-avg-bl](img34/v034_r200c2_rss_avg.png) #### CPU utilization @@ -190,13 +190,13 @@ The best metric from Prometheus to gauge CPU utilization in a Unix machine is `l as it usually appears in the [output of `top`](https://www.digitalocean.com/community/tutorials/load-average-in-linux). -![load1](./img/200nodes_tm037/v037_r200c2_load1.png) +![load1](img37/200nodes_tm037/v037_r200c2_load1.png) It is contained below 5 on most nodes. **This plot yields similar results to the baseline**: -![load1](../v034/img/v034_r200c2_load1.png) +![load1](img34/v034_r200c2_load1.png) ### Test Result @@ -211,18 +211,18 @@ Version: 1cf9d8e276afe8595cba960b51cd056514965fd1 We use the same load as in the baseline: `c=4,r=800`. Just as in the baseline tests, the version of CometBFT used for these tests is affected by #9539. -See this paragraph in the [baseline report](../v034/README.md#rotating-node-testnet) for further details. +See this paragraph in the [baseline report](CometBFT-QA-34.md#rotating-node-testnet) for further details. Finally, note that this setup allows for a fairer comparison between this version and the baseline. ### Latencies The plot of all latencies can be seen here. -![rotating-all-latencies](./img/200nodes_tm037/v037_rotating_latencies.png) +![rotating-all-latencies](img37/200nodes_tm037/v037_rotating_latencies.png) Which is similar to the baseline. -![rotating-all-latencies-bl](../v034/img/v034_rotating_latencies_uniq.png) +![rotating-all-latencies-bl](img34/v034_rotating_latencies_uniq.png) Note that we are comparing against the baseline plot with _unique_ transactions. This is because the problem with duplicate transactions @@ -238,27 +238,27 @@ We also show the baseline results for comparison. The blocks produced per minute are the gradient of this plot. -![rotating-heights](./img/200nodes_tm037/v037_rotating_heights.png) +![rotating-heights](img37/200nodes_tm037/v037_rotating_heights.png) Over a period of 4446 seconds, the height goes from 5 to 3323. This results in an average of 45 blocks produced per minute, which is similar to the baseline, shown below. -![rotating-heights-bl](../v034/img/v034_rotating_heights.png) +![rotating-heights-bl](img34/v034_rotating_heights.png) The following two plots show only the heights reported by ephemeral nodes. The second plot is the baseline plot for comparison. -![rotating-heights-ephe](./img/200nodes_tm037/v037_rotating_heights_ephe.png) +![rotating-heights-ephe](img37/200nodes_tm037/v037_rotating_heights_ephe.png) -![rotating-heights-ephe-bl](../v034/img/v034_rotating_heights_ephe.png) +![rotating-heights-ephe-bl](img34/v034_rotating_heights_ephe.png) By the length of the segments, we can see that ephemeral nodes in `v0.37` catch up slightly faster. The transactions processed per minute are the gradient of this plot. -![rotating-total-txs](./img/200nodes_tm037/v037_rotating_total-txs.png) +![rotating-total-txs](img37/200nodes_tm037/v037_rotating_total-txs.png) Over a period of 3852 seconds, the total goes from 597 to 267298 transactions in one of the validators, resulting in 4154 transactions per minute, which is slightly lower than the baseline, @@ -266,17 +266,17 @@ although the baseline had to deal with duplicate transactions. For comparison, this is the baseline plot. -![rotating-total-txs-bl](../v034/img/v034_rotating_total-txs.png) +![rotating-total-txs-bl](img34/v034_rotating_total-txs.png) #### Peers The plot below shows the evolution of the number of peers throughout the experiment. -![rotating-peers](./img/200nodes_tm037/v037_rotating_peers.png) +![rotating-peers](img37/200nodes_tm037/v037_rotating_peers.png) This is the baseline plot, for comparison. -![rotating-peers-bl](../v034/img/v034_rotating_peers.png) +![rotating-peers-bl](img34/v034_rotating_peers.png) The plotted values and their evolution are comparable in both plots. @@ -287,9 +287,9 @@ For further details on these plots, see the baseline report. The average Resident Set Size (RSS) over all processes looks slightly more stable on `v0.37` (first plot) than on the baseline (second plot). -![rotating-rss-avg](./img/200nodes_tm037/v037_rotating_rss_avg.png) +![rotating-rss-avg](img37/200nodes_tm037/v037_rotating_rss_avg.png) -![rotating-rss-avg-bl](../v034/img/v034_rotating_rss_avg.png) +![rotating-rss-avg-bl](img34/v034_rotating_rss_avg.png) The memory taken by the validators and the ephemeral nodes when they are up is comparable (not shown in the plots), just as observed in the baseline. @@ -298,11 +298,9 @@ just as observed in the baseline. The plot shows metric `load1` for all nodes. -![rotating-load1](./img/200nodes_tm037/200nodes_tm037/v037_rotating_load1.png) +![rotating-load1](img37/200nodes_tm037/v037_rotating_load1.png) -This is the baseline plot. - -![rotating-load1-bl](../v034/img/v034_rotating_load1.png) +![rotating-load1-bl](img34/v034_rotating_load1.png) In both cases, it is contained under 5 most of the time, which is considered normal load. The green line in the `v0.37` plot and the purple line in the baseline plot (`v0.34`) diff --git a/docs/qa/v034/img/baseline/avg_cpu.png b/docs/qa/img34/baseline/avg_cpu.png similarity index 100% rename from docs/qa/v034/img/baseline/avg_cpu.png rename to docs/qa/img34/baseline/avg_cpu.png diff --git a/docs/qa/v034/img/baseline/avg_memory.png b/docs/qa/img34/baseline/avg_memory.png similarity index 100% rename from docs/qa/v034/img/baseline/avg_memory.png rename to docs/qa/img34/baseline/avg_memory.png diff --git a/docs/qa/v034/img/baseline/avg_mempool_size.png b/docs/qa/img34/baseline/avg_mempool_size.png similarity index 100% rename from docs/qa/v034/img/baseline/avg_mempool_size.png rename to docs/qa/img34/baseline/avg_mempool_size.png diff --git a/docs/qa/v034/img/baseline/block_rate_regular.png b/docs/qa/img34/baseline/block_rate_regular.png similarity index 100% rename from docs/qa/v034/img/baseline/block_rate_regular.png rename to docs/qa/img34/baseline/block_rate_regular.png diff --git a/docs/qa/v034/img/baseline/cpu.png b/docs/qa/img34/baseline/cpu.png similarity index 100% rename from docs/qa/v034/img/baseline/cpu.png rename to docs/qa/img34/baseline/cpu.png diff --git a/docs/qa/v034/img/baseline/memory.png b/docs/qa/img34/baseline/memory.png similarity index 100% rename from docs/qa/v034/img/baseline/memory.png rename to docs/qa/img34/baseline/memory.png diff --git a/docs/qa/v034/img/baseline/mempool_size.png b/docs/qa/img34/baseline/mempool_size.png similarity index 100% rename from docs/qa/v034/img/baseline/mempool_size.png rename to docs/qa/img34/baseline/mempool_size.png diff --git a/docs/qa/v034/img/baseline/peers.png b/docs/qa/img34/baseline/peers.png similarity index 100% rename from docs/qa/v034/img/baseline/peers.png rename to docs/qa/img34/baseline/peers.png diff --git a/docs/qa/v034/img/baseline/rounds.png b/docs/qa/img34/baseline/rounds.png similarity index 100% rename from docs/qa/v034/img/baseline/rounds.png rename to docs/qa/img34/baseline/rounds.png diff --git a/docs/qa/v034/img/baseline/total_txs_rate_regular.png b/docs/qa/img34/baseline/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v034/img/baseline/total_txs_rate_regular.png rename to docs/qa/img34/baseline/total_txs_rate_regular.png diff --git a/docs/qa/v034/img/cmt1tm1/all_experiments.png b/docs/qa/img34/cmt1tm1/all_experiments.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/all_experiments.png rename to docs/qa/img34/cmt1tm1/all_experiments.png diff --git a/docs/qa/v034/img/cmt1tm1/avg_cpu.png b/docs/qa/img34/cmt1tm1/avg_cpu.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/avg_cpu.png rename to docs/qa/img34/cmt1tm1/avg_cpu.png diff --git a/docs/qa/v034/img/cmt1tm1/avg_memory.png b/docs/qa/img34/cmt1tm1/avg_memory.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/avg_memory.png rename to docs/qa/img34/cmt1tm1/avg_memory.png diff --git a/docs/qa/v034/img/cmt1tm1/avg_mempool_size.png b/docs/qa/img34/cmt1tm1/avg_mempool_size.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/avg_mempool_size.png rename to docs/qa/img34/cmt1tm1/avg_mempool_size.png diff --git a/docs/qa/v034/img/cmt1tm1/block_rate_regular.png b/docs/qa/img34/cmt1tm1/block_rate_regular.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/block_rate_regular.png rename to docs/qa/img34/cmt1tm1/block_rate_regular.png diff --git a/docs/qa/v034/img/cmt1tm1/cpu.png b/docs/qa/img34/cmt1tm1/cpu.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/cpu.png rename to docs/qa/img34/cmt1tm1/cpu.png diff --git a/docs/qa/v034/img/cmt1tm1/memory.png b/docs/qa/img34/cmt1tm1/memory.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/memory.png rename to docs/qa/img34/cmt1tm1/memory.png diff --git a/docs/qa/v034/img/cmt1tm1/mempool_size.png b/docs/qa/img34/cmt1tm1/mempool_size.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/mempool_size.png rename to docs/qa/img34/cmt1tm1/mempool_size.png diff --git a/docs/qa/v034/img/cmt1tm1/peers.png b/docs/qa/img34/cmt1tm1/peers.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/peers.png rename to docs/qa/img34/cmt1tm1/peers.png diff --git a/docs/qa/v034/img/cmt1tm1/rounds.png b/docs/qa/img34/cmt1tm1/rounds.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/rounds.png rename to docs/qa/img34/cmt1tm1/rounds.png diff --git a/docs/qa/v034/img/cmt1tm1/total_txs_rate_regular.png b/docs/qa/img34/cmt1tm1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v034/img/cmt1tm1/total_txs_rate_regular.png rename to docs/qa/img34/cmt1tm1/total_txs_rate_regular.png diff --git a/docs/qa/v034/img/cmt2tm1/all_experiments.png b/docs/qa/img34/cmt2tm1/all_experiments.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/all_experiments.png rename to docs/qa/img34/cmt2tm1/all_experiments.png diff --git a/docs/qa/v034/img/cmt2tm1/avg_cpu.png b/docs/qa/img34/cmt2tm1/avg_cpu.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/avg_cpu.png rename to docs/qa/img34/cmt2tm1/avg_cpu.png diff --git a/docs/qa/v034/img/cmt2tm1/avg_memory.png b/docs/qa/img34/cmt2tm1/avg_memory.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/avg_memory.png rename to docs/qa/img34/cmt2tm1/avg_memory.png diff --git a/docs/qa/v034/img/cmt2tm1/avg_mempool_size.png b/docs/qa/img34/cmt2tm1/avg_mempool_size.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/avg_mempool_size.png rename to docs/qa/img34/cmt2tm1/avg_mempool_size.png diff --git a/docs/qa/v034/img/cmt2tm1/block_rate_regular.png b/docs/qa/img34/cmt2tm1/block_rate_regular.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/block_rate_regular.png rename to docs/qa/img34/cmt2tm1/block_rate_regular.png diff --git a/docs/qa/v034/img/cmt2tm1/cpu.png b/docs/qa/img34/cmt2tm1/cpu.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/cpu.png rename to docs/qa/img34/cmt2tm1/cpu.png diff --git a/docs/qa/v034/img/cmt2tm1/memory.png b/docs/qa/img34/cmt2tm1/memory.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/memory.png rename to docs/qa/img34/cmt2tm1/memory.png diff --git a/docs/qa/v034/img/cmt2tm1/mempool_size.png b/docs/qa/img34/cmt2tm1/mempool_size.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/mempool_size.png rename to docs/qa/img34/cmt2tm1/mempool_size.png diff --git a/docs/qa/v034/img/cmt2tm1/peers.png b/docs/qa/img34/cmt2tm1/peers.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/peers.png rename to docs/qa/img34/cmt2tm1/peers.png diff --git a/docs/qa/v034/img/cmt2tm1/rounds.png b/docs/qa/img34/cmt2tm1/rounds.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/rounds.png rename to docs/qa/img34/cmt2tm1/rounds.png diff --git a/docs/qa/v034/img/cmt2tm1/total_txs_rate_regular.png b/docs/qa/img34/cmt2tm1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v034/img/cmt2tm1/total_txs_rate_regular.png rename to docs/qa/img34/cmt2tm1/total_txs_rate_regular.png diff --git a/docs/qa/v034/img/homogeneous/all_experiments.png b/docs/qa/img34/homogeneous/all_experiments.png similarity index 100% rename from docs/qa/v034/img/homogeneous/all_experiments.png rename to docs/qa/img34/homogeneous/all_experiments.png diff --git a/docs/qa/v034/img/homogeneous/avg_cpu.png b/docs/qa/img34/homogeneous/avg_cpu.png similarity index 100% rename from docs/qa/v034/img/homogeneous/avg_cpu.png rename to docs/qa/img34/homogeneous/avg_cpu.png diff --git a/docs/qa/v034/img/homogeneous/avg_memory.png b/docs/qa/img34/homogeneous/avg_memory.png similarity index 100% rename from docs/qa/v034/img/homogeneous/avg_memory.png rename to docs/qa/img34/homogeneous/avg_memory.png diff --git a/docs/qa/v034/img/homogeneous/avg_mempool_size.png b/docs/qa/img34/homogeneous/avg_mempool_size.png similarity index 100% rename from docs/qa/v034/img/homogeneous/avg_mempool_size.png rename to docs/qa/img34/homogeneous/avg_mempool_size.png diff --git a/docs/qa/v034/img/homogeneous/block_rate_regular.png b/docs/qa/img34/homogeneous/block_rate_regular.png similarity index 100% rename from docs/qa/v034/img/homogeneous/block_rate_regular.png rename to docs/qa/img34/homogeneous/block_rate_regular.png diff --git a/docs/qa/v034/img/homogeneous/cpu.png b/docs/qa/img34/homogeneous/cpu.png similarity index 100% rename from docs/qa/v034/img/homogeneous/cpu.png rename to docs/qa/img34/homogeneous/cpu.png diff --git a/docs/qa/v034/img/homogeneous/memory.png b/docs/qa/img34/homogeneous/memory.png similarity index 100% rename from docs/qa/v034/img/homogeneous/memory.png rename to docs/qa/img34/homogeneous/memory.png diff --git a/docs/qa/v034/img/homogeneous/mempool_size.png b/docs/qa/img34/homogeneous/mempool_size.png similarity index 100% rename from docs/qa/v034/img/homogeneous/mempool_size.png rename to docs/qa/img34/homogeneous/mempool_size.png diff --git a/docs/qa/v034/img/homogeneous/peers.png b/docs/qa/img34/homogeneous/peers.png similarity index 100% rename from docs/qa/v034/img/homogeneous/peers.png rename to docs/qa/img34/homogeneous/peers.png diff --git a/docs/qa/v034/img/homogeneous/rounds.png b/docs/qa/img34/homogeneous/rounds.png similarity index 100% rename from docs/qa/v034/img/homogeneous/rounds.png rename to docs/qa/img34/homogeneous/rounds.png diff --git a/docs/qa/v034/img/homogeneous/total_txs_rate_regular.png b/docs/qa/img34/homogeneous/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v034/img/homogeneous/total_txs_rate_regular.png rename to docs/qa/img34/homogeneous/total_txs_rate_regular.png diff --git a/docs/qa/v034/img/v034_200node_latencies.png b/docs/qa/img34/v034_200node_latencies.png similarity index 100% rename from docs/qa/v034/img/v034_200node_latencies.png rename to docs/qa/img34/v034_200node_latencies.png diff --git a/docs/qa/v034/img/v034_200node_latencies_zoomed.png b/docs/qa/img34/v034_200node_latencies_zoomed.png similarity index 100% rename from docs/qa/v034/img/v034_200node_latencies_zoomed.png rename to docs/qa/img34/v034_200node_latencies_zoomed.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/all_experiments.png b/docs/qa/img34/v034_200node_tm2cmt1/all_experiments.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/all_experiments.png rename to docs/qa/img34/v034_200node_tm2cmt1/all_experiments.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/avg_cpu.png b/docs/qa/img34/v034_200node_tm2cmt1/avg_cpu.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/avg_cpu.png rename to docs/qa/img34/v034_200node_tm2cmt1/avg_cpu.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/avg_memory.png b/docs/qa/img34/v034_200node_tm2cmt1/avg_memory.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/avg_memory.png rename to docs/qa/img34/v034_200node_tm2cmt1/avg_memory.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/avg_mempool_size.png b/docs/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/avg_mempool_size.png rename to docs/qa/img34/v034_200node_tm2cmt1/avg_mempool_size.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/block_rate_regular.png b/docs/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/block_rate_regular.png rename to docs/qa/img34/v034_200node_tm2cmt1/block_rate_regular.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/c2r200_merged.png b/docs/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/c2r200_merged.png rename to docs/qa/img34/v034_200node_tm2cmt1/c2r200_merged.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/cpu.png b/docs/qa/img34/v034_200node_tm2cmt1/cpu.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/cpu.png rename to docs/qa/img34/v034_200node_tm2cmt1/cpu.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/memory.png b/docs/qa/img34/v034_200node_tm2cmt1/memory.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/memory.png rename to docs/qa/img34/v034_200node_tm2cmt1/memory.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/mempool_size.png b/docs/qa/img34/v034_200node_tm2cmt1/mempool_size.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/mempool_size.png rename to docs/qa/img34/v034_200node_tm2cmt1/mempool_size.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/peers.png b/docs/qa/img34/v034_200node_tm2cmt1/peers.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/peers.png rename to docs/qa/img34/v034_200node_tm2cmt1/peers.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/rounds.png b/docs/qa/img34/v034_200node_tm2cmt1/rounds.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/rounds.png rename to docs/qa/img34/v034_200node_tm2cmt1/rounds.png diff --git a/docs/qa/v034/img/v034_200node_tm2cmt1/total_txs_rate_regular.png b/docs/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v034/img/v034_200node_tm2cmt1/total_txs_rate_regular.png rename to docs/qa/img34/v034_200node_tm2cmt1/total_txs_rate_regular.png diff --git a/docs/qa/v034/img/v034_latency_throughput.png b/docs/qa/img34/v034_latency_throughput.png similarity index 100% rename from docs/qa/v034/img/v034_latency_throughput.png rename to docs/qa/img34/v034_latency_throughput.png diff --git a/docs/qa/v034/img/v034_r200c2_heights.png b/docs/qa/img34/v034_r200c2_heights.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_heights.png rename to docs/qa/img34/v034_r200c2_heights.png diff --git a/docs/qa/v034/img/v034_r200c2_load-runner.png b/docs/qa/img34/v034_r200c2_load-runner.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_load-runner.png rename to docs/qa/img34/v034_r200c2_load-runner.png diff --git a/docs/qa/v034/img/v034_r200c2_load1.png b/docs/qa/img34/v034_r200c2_load1.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_load1.png rename to docs/qa/img34/v034_r200c2_load1.png diff --git a/docs/qa/v034/img/v034_r200c2_mempool_size.png b/docs/qa/img34/v034_r200c2_mempool_size.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_mempool_size.png rename to docs/qa/img34/v034_r200c2_mempool_size.png diff --git a/docs/qa/v034/img/v034_r200c2_mempool_size_avg.png b/docs/qa/img34/v034_r200c2_mempool_size_avg.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_mempool_size_avg.png rename to docs/qa/img34/v034_r200c2_mempool_size_avg.png diff --git a/docs/qa/v034/img/v034_r200c2_peers.png b/docs/qa/img34/v034_r200c2_peers.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_peers.png rename to docs/qa/img34/v034_r200c2_peers.png diff --git a/docs/qa/v034/img/v034_r200c2_rounds.png b/docs/qa/img34/v034_r200c2_rounds.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_rounds.png rename to docs/qa/img34/v034_r200c2_rounds.png diff --git a/docs/qa/v034/img/v034_r200c2_rss.png b/docs/qa/img34/v034_r200c2_rss.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_rss.png rename to docs/qa/img34/v034_r200c2_rss.png diff --git a/docs/qa/v034/img/v034_r200c2_rss_avg.png b/docs/qa/img34/v034_r200c2_rss_avg.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_rss_avg.png rename to docs/qa/img34/v034_r200c2_rss_avg.png diff --git a/docs/qa/v034/img/v034_r200c2_total-txs.png b/docs/qa/img34/v034_r200c2_total-txs.png similarity index 100% rename from docs/qa/v034/img/v034_r200c2_total-txs.png rename to docs/qa/img34/v034_r200c2_total-txs.png diff --git a/docs/qa/v034/img/v034_report_tabbed.txt b/docs/qa/img34/v034_report_tabbed.txt similarity index 100% rename from docs/qa/v034/img/v034_report_tabbed.txt rename to docs/qa/img34/v034_report_tabbed.txt diff --git a/docs/qa/v034/img/v034_rotating_heights.png b/docs/qa/img34/v034_rotating_heights.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_heights.png rename to docs/qa/img34/v034_rotating_heights.png diff --git a/docs/qa/v034/img/v034_rotating_heights_ephe.png b/docs/qa/img34/v034_rotating_heights_ephe.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_heights_ephe.png rename to docs/qa/img34/v034_rotating_heights_ephe.png diff --git a/docs/qa/v034/img/v034_rotating_latencies.png b/docs/qa/img34/v034_rotating_latencies.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_latencies.png rename to docs/qa/img34/v034_rotating_latencies.png diff --git a/docs/qa/v034/img/v034_rotating_latencies_uniq.png b/docs/qa/img34/v034_rotating_latencies_uniq.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_latencies_uniq.png rename to docs/qa/img34/v034_rotating_latencies_uniq.png diff --git a/docs/qa/v034/img/v034_rotating_load1.png b/docs/qa/img34/v034_rotating_load1.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_load1.png rename to docs/qa/img34/v034_rotating_load1.png diff --git a/docs/qa/v034/img/v034_rotating_peers.png b/docs/qa/img34/v034_rotating_peers.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_peers.png rename to docs/qa/img34/v034_rotating_peers.png diff --git a/docs/qa/v034/img/v034_rotating_rss_avg.png b/docs/qa/img34/v034_rotating_rss_avg.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_rss_avg.png rename to docs/qa/img34/v034_rotating_rss_avg.png diff --git a/docs/qa/v034/img/v034_rotating_total-txs.png b/docs/qa/img34/v034_rotating_total-txs.png similarity index 100% rename from docs/qa/v034/img/v034_rotating_total-txs.png rename to docs/qa/img34/v034_rotating_total-txs.png diff --git a/docs/qa/v037/img/200nodes_cmt037/all_experiments.png b/docs/qa/img37/200nodes_cmt037/all_experiments.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/all_experiments.png rename to docs/qa/img37/200nodes_cmt037/all_experiments.png diff --git a/docs/qa/v037/img/200nodes_cmt037/avg_mempool_size.png b/docs/qa/img37/200nodes_cmt037/avg_mempool_size.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/avg_mempool_size.png rename to docs/qa/img37/200nodes_cmt037/avg_mempool_size.png diff --git a/docs/qa/v037/img/200nodes_cmt037/block_rate.png b/docs/qa/img37/200nodes_cmt037/block_rate.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/block_rate.png rename to docs/qa/img37/200nodes_cmt037/block_rate.png diff --git a/docs/qa/v037/img/200nodes_cmt037/cpu.png b/docs/qa/img37/200nodes_cmt037/cpu.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/cpu.png rename to docs/qa/img37/200nodes_cmt037/cpu.png diff --git a/docs/qa/v037/img/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png b/docs/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png rename to docs/qa/img37/200nodes_cmt037/e_75cb89a8-f876-4698-82f3-8aaab0b361af.png diff --git a/docs/qa/v037/img/200nodes_cmt037/memory.png b/docs/qa/img37/200nodes_cmt037/memory.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/memory.png rename to docs/qa/img37/200nodes_cmt037/memory.png diff --git a/docs/qa/v037/img/200nodes_cmt037/mempool_size.png b/docs/qa/img37/200nodes_cmt037/mempool_size.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/mempool_size.png rename to docs/qa/img37/200nodes_cmt037/mempool_size.png diff --git a/docs/qa/v037/img/200nodes_cmt037/peers.png b/docs/qa/img37/200nodes_cmt037/peers.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/peers.png rename to docs/qa/img37/200nodes_cmt037/peers.png diff --git a/docs/qa/v037/img/200nodes_cmt037/rounds.png b/docs/qa/img37/200nodes_cmt037/rounds.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/rounds.png rename to docs/qa/img37/200nodes_cmt037/rounds.png diff --git a/docs/qa/v037/img/200nodes_cmt037/total_txs_rate.png b/docs/qa/img37/200nodes_cmt037/total_txs_rate.png similarity index 100% rename from docs/qa/v037/img/200nodes_cmt037/total_txs_rate.png rename to docs/qa/img37/200nodes_cmt037/total_txs_rate.png diff --git a/docs/qa/v037/img/200nodes_tm037/avg_mempool_size.png b/docs/qa/img37/200nodes_tm037/avg_mempool_size.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/avg_mempool_size.png rename to docs/qa/img37/200nodes_tm037/avg_mempool_size.png diff --git a/docs/qa/v037/img/200nodes_tm037/block_rate_regular.png b/docs/qa/img37/200nodes_tm037/block_rate_regular.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/block_rate_regular.png rename to docs/qa/img37/200nodes_tm037/block_rate_regular.png diff --git a/docs/qa/v037/img/200nodes_tm037/cpu.png b/docs/qa/img37/200nodes_tm037/cpu.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/cpu.png rename to docs/qa/img37/200nodes_tm037/cpu.png diff --git a/docs/qa/v037/img/200nodes_tm037/memory.png b/docs/qa/img37/200nodes_tm037/memory.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/memory.png rename to docs/qa/img37/200nodes_tm037/memory.png diff --git a/docs/qa/v037/img/200nodes_tm037/mempool_size.png b/docs/qa/img37/200nodes_tm037/mempool_size.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/mempool_size.png rename to docs/qa/img37/200nodes_tm037/mempool_size.png diff --git a/docs/qa/v037/img/200nodes_tm037/peers.png b/docs/qa/img37/200nodes_tm037/peers.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/peers.png rename to docs/qa/img37/200nodes_tm037/peers.png diff --git a/docs/qa/v037/img/200nodes_tm037/rounds.png b/docs/qa/img37/200nodes_tm037/rounds.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/rounds.png rename to docs/qa/img37/200nodes_tm037/rounds.png diff --git a/docs/qa/v037/img/200nodes_tm037/total_txs_rate_regular.png b/docs/qa/img37/200nodes_tm037/total_txs_rate_regular.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/total_txs_rate_regular.png rename to docs/qa/img37/200nodes_tm037/total_txs_rate_regular.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_200node_latencies.png b/docs/qa/img37/200nodes_tm037/v037_200node_latencies.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_200node_latencies.png rename to docs/qa/img37/200nodes_tm037/v037_200node_latencies.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_latency_throughput.png b/docs/qa/img37/200nodes_tm037/v037_latency_throughput.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_latency_throughput.png rename to docs/qa/img37/200nodes_tm037/v037_latency_throughput.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_heights.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_heights.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_heights.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_heights.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_load1.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_load1.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_load1.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_load1.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_mempool_size.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_mempool_size.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_mempool_size_avg.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_mempool_size_avg.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_mempool_size_avg.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_peers.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_peers.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_peers.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_peers.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_rounds.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_rounds.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_rounds.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_rounds.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_rss.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_rss.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_rss.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_rss.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_rss_avg.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_rss_avg.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_rss_avg.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_r200c2_total-txs.png b/docs/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_r200c2_total-txs.png rename to docs/qa/img37/200nodes_tm037/v037_r200c2_total-txs.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_report_tabbed.txt b/docs/qa/img37/200nodes_tm037/v037_report_tabbed.txt similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_report_tabbed.txt rename to docs/qa/img37/200nodes_tm037/v037_report_tabbed.txt diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_heights.png b/docs/qa/img37/200nodes_tm037/v037_rotating_heights.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_heights.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_heights.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_heights_ephe.png b/docs/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_heights_ephe.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_heights_ephe.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_latencies.png b/docs/qa/img37/200nodes_tm037/v037_rotating_latencies.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_latencies.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_latencies.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_load1.png b/docs/qa/img37/200nodes_tm037/v037_rotating_load1.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_load1.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_load1.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_peers.png b/docs/qa/img37/200nodes_tm037/v037_rotating_peers.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_peers.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_peers.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_rss_avg.png b/docs/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_rss_avg.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_rss_avg.png diff --git a/docs/qa/v037/img/200nodes_tm037/v037_rotating_total-txs.png b/docs/qa/img37/200nodes_tm037/v037_rotating_total-txs.png similarity index 100% rename from docs/qa/v037/img/200nodes_tm037/v037_rotating_total-txs.png rename to docs/qa/img37/200nodes_tm037/v037_rotating_total-txs.png diff --git a/docs/qa/method.md b/docs/qa/method.md index 5326f935a1b..6de0cbcf80c 100644 --- a/docs/qa/method.md +++ b/docs/qa/method.md @@ -1,6 +1,8 @@ --- order: 1 -title: Method +parent: + title: Method + order: 1 --- # Method @@ -106,11 +108,11 @@ The CometBFT team should improve it at every iteration to increase the amount of 3. File `report.txt` contains an unordered list of experiments with varying concurrent connections and transaction rate * If you are looking for the saturation point * Create files `report01.txt`, `report02.txt`, `report04.txt` and, for each experiment in file `report.txt`, - copy its related lines to the filename that matches the number of connections, for example + copy its related lines to the filename that matches the number of connections, for example ```bash for cnum in 1 2 3 4; do echo "$cnum"; grep "Connections: $cnum" results/report.txt -B 2 -A 10 > results/report$cnum.txt; done ``` - + * Sort the experiments in `report01.txt` in ascending tx rate order. Likewise for `report02.txt` and `report04.txt`. * Otherwise just keep `report.txt`, and skip step 4. 4. Generate file `report_tabbed.txt` by showing the contents `report01.txt`, `report02.txt`, `report04.txt` side by side @@ -229,7 +231,7 @@ This section explains how the tests were carried out for reproducibility purpose 7. On a different shell, * run `make runload ROTATE_CONNECTIONS=X ROTATE_TX_RATE=Y` * `X` and `Y` should reflect a load below the saturation point (see, e.g., - [this paragraph](./v034/README.md#finding-the-saturation-point) for further info) + [this paragraph](CometBFT-QA-34.md#finding-the-saturation-point) for further info) 8. Run `make rotate` to start the script that creates the ephemeral nodes, and kills them when they are caught up. * WARNING: If you run this command from your laptop, the laptop needs to be up and connected for full length of the experiment. diff --git a/go.mod b/go.mod index 8d982c642d0..f64bc2c8eb7 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( github.com/go-kit/kit v0.12.0 github.com/go-kit/log v0.2.1 github.com/go-logfmt/logfmt v0.6.0 - github.com/golang/protobuf v1.5.2 - github.com/golangci/golangci-lint v1.51.2 + github.com/golang/protobuf v1.5.3 + github.com/golangci/golangci-lint v1.52.0 github.com/google/orderedcode v0.0.1 github.com/gorilla/websocket v1.5.0 github.com/informalsystems/tm-load-test v1.3.0 @@ -23,7 +23,7 @@ require ( github.com/pointlander/peg v1.0.1 github.com/prometheus/client_golang v1.14.0 github.com/prometheus/client_model v0.3.0 - github.com/prometheus/common v0.40.0 + github.com/prometheus/common v0.42.0 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 github.com/rs/cors v1.8.3 github.com/sasha-s/go-deadlock v0.3.1 @@ -31,13 +31,13 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.8.2 - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.7.0 + golang.org/x/crypto v0.7.0 + golang.org/x/net v0.8.0 google.golang.org/grpc v1.53.0 ) require ( - github.com/bufbuild/buf v1.14.0 + github.com/bufbuild/buf v1.15.1 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 ) @@ -47,23 +47,22 @@ require ( github.com/btcsuite/btcd/btcutil v1.1.3 github.com/cometbft/cometbft-db v0.7.0 github.com/cosmos/gogoproto v1.4.6 - github.com/go-git/go-git/v5 v5.5.2 + github.com/go-git/go-git/v5 v5.6.1 github.com/gofrs/uuid v4.4.0+incompatible - github.com/gogo/protobuf v1.3.2 github.com/google/uuid v1.3.0 github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae - github.com/vektra/mockery/v2 v2.20.2 + github.com/vektra/mockery/v2 v2.23.1 golang.org/x/sync v0.1.0 gonum.org/v1/gonum v0.12.0 - google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 + google.golang.org/protobuf v1.30.0 ) require ( 4d63.com/gocheckcompilerdirectives v1.2.1 // indirect 4d63.com/gochecknoglobals v0.2.1 // indirect - github.com/Abirdcfly/dupword v0.0.9 // indirect - github.com/Antonboom/errname v0.1.7 // indirect - github.com/Antonboom/nilnil v0.1.1 // indirect + github.com/Abirdcfly/dupword v0.0.11 // indirect + github.com/Antonboom/errname v0.1.9 // indirect + github.com/Antonboom/nilnil v0.1.3 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 // indirect @@ -71,40 +70,40 @@ require ( github.com/Microsoft/go-winio v0.6.0 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/OpenPeeDeeP/depguard v1.1.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect - github.com/acomagu/bufpipe v1.0.3 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect github.com/alexkohler/prealloc v1.0.0 // indirect github.com/alingse/asasalint v0.0.11 // indirect - github.com/ashanbrown/forbidigo v1.4.0 // indirect + github.com/ashanbrown/forbidigo v1.5.1 // indirect github.com/ashanbrown/makezero v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bkielbasa/cyclop v1.2.0 // indirect github.com/blizzy78/varnamelen v0.8.0 // indirect github.com/bombsimon/wsl/v3 v3.4.0 // indirect - github.com/breml/bidichk v0.2.3 // indirect - github.com/breml/errchkjson v0.3.0 // indirect - github.com/bufbuild/connect-go v1.5.0 // indirect - github.com/bufbuild/protocompile v0.2.0 // indirect + github.com/breml/bidichk v0.2.4 // indirect + github.com/breml/errchkjson v0.3.1 // indirect + github.com/bufbuild/connect-go v1.5.2 // indirect + github.com/bufbuild/protocompile v0.5.1 // indirect github.com/butuzov/ireturn v0.1.1 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/charithe/durationcheck v0.0.9 // indirect - github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 // indirect + github.com/charithe/durationcheck v0.0.10 // indirect + github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 // indirect github.com/chigopher/pathlib v0.12.0 // indirect github.com/cloudflare/circl v1.3.1 // indirect github.com/containerd/continuity v0.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect - github.com/daixiang0/gci v0.9.1 // indirect + github.com/daixiang0/gci v0.10.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/denis-tingaikin/go-header v0.4.3 // indirect github.com/dgraph-io/badger/v2 v2.2007.4 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect - github.com/docker/cli v20.10.23+incompatible // indirect + github.com/docker/cli v23.0.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v23.0.0+incompatible // indirect + github.com/docker/docker v23.0.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -115,20 +114,20 @@ require ( github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.15.0 // indirect github.com/fatih/structtag v1.2.0 // indirect github.com/felixge/fgprof v0.9.3 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/go-chi/chi/v5 v5.0.8 // indirect - github.com/go-critic/go-critic v0.6.7 // indirect + github.com/go-critic/go-critic v0.7.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.4.0 // indirect + github.com/go-git/go-billy/v5 v5.4.1 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-toolsmith/astcast v1.1.0 // indirect - github.com/go-toolsmith/astcopy v1.0.3 // indirect + github.com/go-toolsmith/astcopy v1.1.0 // indirect github.com/go-toolsmith/astequal v1.1.0 // indirect github.com/go-toolsmith/astfmt v1.1.0 // indirect github.com/go-toolsmith/astp v1.1.0 // indirect @@ -137,6 +136,8 @@ require ( github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/uuid/v5 v5.0.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.0.0 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect @@ -151,7 +152,7 @@ require ( github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-containerregistry v0.13.0 // indirect - github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f // indirect + github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 // indirect github.com/gostaticanalysis/analysisutil v0.7.1 // indirect github.com/gostaticanalysis/comment v1.4.2 // indirect @@ -163,22 +164,23 @@ require ( github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/hexops/gotextdiff v1.0.3 // indirect + github.com/iancoleman/strcase v0.2.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect github.com/jgautheron/goconst v1.5.1 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect + github.com/jinzhu/copier v0.3.5 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect github.com/julz/importas v0.1.0 // indirect - github.com/junk1tm/musttag v0.4.5 // indirect + github.com/junk1tm/musttag v0.5.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/kisielk/errcheck v1.6.3 // indirect github.com/kisielk/gotool v1.0.0 // indirect - github.com/kkHAIKE/contextcheck v1.1.3 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/kkHAIKE/contextcheck v1.1.4 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/kulti/thelper v0.6.3 // indirect github.com/kunwardeep/paralleltest v1.0.6 // indirect @@ -189,45 +191,43 @@ require ( github.com/lufeee/execinquery v1.2.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/maratori/testableexamples v1.0.0 // indirect - github.com/maratori/testpackage v1.1.0 // indirect - github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 // indirect + github.com/maratori/testpackage v1.1.1 // indirect + github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mbilski/exhaustivestruct v1.2.0 // indirect - github.com/mgechev/revive v1.2.5 // indirect + github.com/mgechev/revive v1.3.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/moricho/tparallel v0.2.1 // indirect + github.com/moricho/tparallel v0.3.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/nishanths/exhaustive v0.9.5 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nunnatsa/ginkgolinter v0.8.1 // indirect + github.com/nunnatsa/ginkgolinter v0.9.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/opencontainers/runc v1.1.3 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect - github.com/pjbgf/sha1cd v0.2.3 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3 // indirect github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4 // indirect - github.com/polyfloyd/go-errorlint v1.1.0 // indirect + github.com/polyfloyd/go-errorlint v1.4.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/quasilyte/go-ruleguard v0.3.19 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect - github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 // indirect + github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect - github.com/rs/zerolog v1.27.0 // indirect + github.com/rs/zerolog v1.29.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect @@ -243,7 +243,7 @@ require ( github.com/sivchari/nosnakecase v1.7.0 // indirect github.com/sivchari/tenv v1.7.1 // indirect github.com/skeema/knownhosts v1.1.0 // indirect - github.com/sonatard/noctx v0.0.1 // indirect + github.com/sonatard/noctx v0.0.2 // indirect github.com/sourcegraph/go-diff v0.7.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect @@ -254,12 +254,12 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect - github.com/tdakkota/asciicheck v0.1.1 // indirect + github.com/tdakkota/asciicheck v0.2.0 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tetafro/godot v1.4.11 // indirect github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e // indirect - github.com/timonwong/loggercheck v0.9.3 // indirect - github.com/tomarrell/wrapcheck/v2 v2.8.0 // indirect + github.com/timonwong/loggercheck v0.9.4 // indirect + github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect github.com/ultraware/funlen v0.0.3 // indirect github.com/ultraware/whitespace v0.0.5 // indirect @@ -269,26 +269,26 @@ require ( github.com/yeya24/promlinter v0.2.0 // indirect gitlab.com/bosi/decorder v0.2.3 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.opentelemetry.io/otel v1.12.0 // indirect - go.opentelemetry.io/otel/sdk v1.12.0 // indirect - go.opentelemetry.io/otel/trace v1.12.0 // indirect + go.opentelemetry.io/otel v1.14.0 // indirect + go.opentelemetry.io/otel/sdk v1.14.0 // indirect + go.opentelemetry.io/otel/trace v1.14.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect + go.uber.org/multierr v1.10.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 // indirect - golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect + golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 // indirect + golang.org/x/mod v0.9.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/tools v0.7.0 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools v2.2.0+incompatible // indirect - honnef.co/go/tools v0.4.2 // indirect + honnef.co/go/tools v0.4.3 // indirect mvdan.cc/gofumpt v0.4.0 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect diff --git a/go.sum b/go.sum index 0ce7f4cf60e..a307ba5909d 100644 --- a/go.sum +++ b/go.sum @@ -40,12 +40,12 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Abirdcfly/dupword v0.0.9 h1:MxprGjKq3yDBICXDgEEsyGirIXfMYXkLNT/agPsE1tk= -github.com/Abirdcfly/dupword v0.0.9/go.mod h1:PzmHVLLZ27MvHSzV7eFmMXSFArWXZPZmfuuziuUrf2g= -github.com/Antonboom/errname v0.1.7 h1:mBBDKvEYwPl4WFFNwec1CZO096G6vzK9vvDQzAwkako= -github.com/Antonboom/errname v0.1.7/go.mod h1:g0ONh16msHIPgJSGsecu1G/dcF2hlYR/0SddnIAGavU= -github.com/Antonboom/nilnil v0.1.1 h1:PHhrh5ANKFWRBh7TdYmyyq2gyT2lotnvFvvFbylF81Q= -github.com/Antonboom/nilnil v0.1.1/go.mod h1:L1jBqoWM7AOeTD+tSquifKSesRHs4ZdaxvZR+xdJEaI= +github.com/Abirdcfly/dupword v0.0.11 h1:z6v8rMETchZXUIuHxYNmlUAuKuB21PeaSymTed16wgU= +github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= +github.com/Antonboom/errname v0.1.9 h1:BZDX4r3l4TBZxZ2o2LNrlGxSHran4d1u4veZdoORTT4= +github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= +github.com/Antonboom/nilnil v0.1.3 h1:6RTbx3d2mcEu3Zwq9TowQpQMVpP75zugwOtqY1RTtcE= +github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -70,11 +70,11 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.1.1 h1:TSUznLjvp/4IUP+OQ0t/4jF4QUyxIcVX8YnghZdunyA= github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= -github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I= -github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -92,8 +92,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuW github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/ashanbrown/forbidigo v1.4.0 h1:spdPbupaSqtWORq1Q4eHBoPBmHtwVyLKwaedbSLc5Sw= -github.com/ashanbrown/forbidigo v1.4.0/go.mod h1:IvgwB5Y4fzqSAj/WVXKWigoTkB0dzI2FBbpKWuh7ph8= +github.com/ashanbrown/forbidigo v1.5.1 h1:WXhzLjOlnuDYPYQo/eFlcFMi8X/kLfvWLYu6CSoebis= +github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1 h1:iCQ87C0V0vSyO+M9E/FZYbu65auqH0lnsOkf5FcB28s= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= @@ -107,10 +107,10 @@ github.com/blizzy78/varnamelen v0.8.0 h1:oqSblyuQvFsW1hbBHh1zfwrKe3kcSj0rnXkKzsQ github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.4.0 h1:RkSxjT3tmlptwfgEgTgU+KYKLI35p/tviNXNXiL2aNU= github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= -github.com/breml/bidichk v0.2.3 h1:qe6ggxpTfA8E75hdjWPZ581sY3a2lnl0IRxLQFelECI= -github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= -github.com/breml/errchkjson v0.3.0 h1:YdDqhfqMT+I1vIxPSas44P+9Z9HzJwCeAzjB8PxP1xw= -github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= +github.com/breml/bidichk v0.2.4 h1:i3yedFWWQ7YzjdZJHnPo9d/xURinSq3OM+gyM43K4/8= +github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= +github.com/breml/errchkjson v0.3.1 h1:hlIeXuspTyt8Y/UmP5qy1JocGNR00KQHgfaNtRAjoxQ= +github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= @@ -135,12 +135,12 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= 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/bufbuild/buf v1.14.0 h1:BSpRDgxC8jKwV+XJXyVuB0PM1na/qL80rNAgzb1PZnU= -github.com/bufbuild/buf v1.14.0/go.mod h1:Z5FtbEZtMdog6dGRZdCvIZTc6lPYaCz3AONEPmXNkyk= -github.com/bufbuild/connect-go v1.5.0 h1:IfbgbzzaaZvF+OM3SfxO2EjtvNJarNAz2DIRuuNjAgc= -github.com/bufbuild/connect-go v1.5.0/go.mod h1:9iNvh/NOsfhNBUH5CtvXeVUskQO1xsrEviH7ZArwZ3I= -github.com/bufbuild/protocompile v0.2.0 h1:BykKTiwLe/Z4WaYKI8qHbD0zCijHI/VhCG5I/MwTwHg= -github.com/bufbuild/protocompile v0.2.0/go.mod h1:tleDrpPTlLUVmgnEoN6qBliKWqJaZFJXqZdFjTd+ocU= +github.com/bufbuild/buf v1.15.1 h1:v7sK2uMEsGX4Z2hvu+xiMheH3C3AKBGfxPBgdUZYDQ8= +github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE= +github.com/bufbuild/connect-go v1.5.2 h1:G4EZd5gF1U1ZhhbVJXplbuUnfKpBZ5j5izqIwu2g2W8= +github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk= +github.com/bufbuild/protocompile v0.5.1 h1:mixz5lJX4Hiz4FpqFREJHIXLfaLBntfaJv1h+/jS+Qg= +github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= @@ -154,10 +154,10 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= -github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348 h1:cy5GCEZLUCshCGCRRUjxHrDUqkB4l5cuUt3ShEckQEo= -github.com/chavacava/garif v0.0.0-20221024190013-b3ef35877348/go.mod h1:f/miWtG3SSuTxKsNK3o58H1xl+XV6ZIfbC6p7lPPB8U= +github.com/charithe/durationcheck v0.0.10 h1:wgw73BiocdBDQPik+zcEoBG/ob8uyBHf2iyoHGPf5w4= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chigopher/pathlib v0.12.0 h1:1GM7fN/IwXXmOHbd1jkMqHD2wUhYqUvafgxTwmLT/q8= github.com/chigopher/pathlib v0.12.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= @@ -194,8 +194,8 @@ github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/curioswitch/go-reassign v0.2.0 h1:G9UZyOcpk/d7Gd6mqYgd8XYWFMw/znxwGDUstnC9DIo= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/daixiang0/gci v0.9.1 h1:jBrwBmBZTDsGsXiaCTLIe9diotp1X4X64zodFrh7l+c= -github.com/daixiang0/gci v0.9.1/go.mod h1:EpVfrztufwVgQRXjnX4zuNinEpLj5OmMjtu/+MB0V0c= +github.com/daixiang0/gci v0.10.1 h1:eheNA3ljF6SxnPD/vE4lCBusVHmV3Rs3dkKvFrJ7MR0= +github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= 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= @@ -216,12 +216,12 @@ github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkz github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/docker/cli v20.10.23+incompatible h1:qwyha/T3rXk9lfuVcn533cKFc7n/6IzL5GXVAgMVPBg= -github.com/docker/cli v20.10.23+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v23.0.1+incompatible h1:LRyWITpGzl2C9e9uGxzisptnxAn1zfZKXy13Ul2Q5oM= +github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v23.0.0+incompatible h1:L6c28tNyqZ4/ub9AZC9d5QUuunoHHfEH4/Ue+h/E5nE= -github.com/docker/docker v23.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v23.0.1+incompatible h1:vjgvJZxprTTE1A37nm+CLNAdwu6xZekyoiVlUZEINcY= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -250,8 +250,8 @@ github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojt github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= +github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= @@ -272,17 +272,17 @@ github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-critic/go-critic v0.6.7 h1:1evPrElnLQ2LZtJfmNDzlieDhjnq36SLgNzisx06oPM= -github.com/go-critic/go-critic v0.6.7/go.mod h1:fYZUijFdcnxgx6wPjQA2QEjIRaNCT0gO8bhexy6/QmE= +github.com/go-critic/go-critic v0.7.0 h1:tqbKzB8pqi0NsRZ+1pyU4aweAF7A7QN0Pi4Q02+rYnQ= +github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE= -github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ= github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= -github.com/go-git/go-git/v5 v5.5.2 h1:v8lgZa5k9ylUw+OR/roJHTxR4QItsNFI5nKtAXFuynw= -github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4BlxtH7OjI= +github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= +github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= 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-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -307,9 +307,8 @@ github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= -github.com/go-toolsmith/astcopy v1.0.3 h1:r0bgSRlMOAgO+BdQnVAcpMSMkrQCnV6ZJmIkrJgcJj0= -github.com/go-toolsmith/astcopy v1.0.3/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= -github.com/go-toolsmith/astequal v1.0.2/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/astequal v1.1.0 h1:kHKm1AWqClYn15R0K1KKE4RG614D46n+nqUQ06E1dTw= github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= @@ -317,7 +316,7 @@ github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsO github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= -github.com/go-toolsmith/pkgload v1.0.2-0.20220101231613-e814995d17c5 h1:eD9POs68PHkwrx7hAB78z1cb6PfGq/jyWn3wJywsH1o= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= @@ -333,6 +332,8 @@ github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= +github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -366,8 +367,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -379,8 +381,8 @@ github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe h1:6RGUuS7EGotKx6 github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 h1:amWTbTGqOZ71ruzrdA+Nx5WA3tV1N0goTspwmKCQvBY= github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= -github.com/golangci/golangci-lint v1.51.2 h1:yIcsT1X9ZYHdSpeWXRT1ORC/FPGSqDHbHsu9uk4FK7M= -github.com/golangci/golangci-lint v1.51.2/go.mod h1:KH9Q7/3glwpYSknxUgUyLlAv46A8fsSKo1hH2wDvkr8= +github.com/golangci/golangci-lint v1.52.0 h1:T7w3tuF1goz64qGV+ML4MgysSl/yUfA3UZJK92oE48A= +github.com/golangci/golangci-lint v1.52.0/go.mod h1:wlTh+d/oVlgZC2yCe6nlxrxNAnuhEQC0Zdygoh72Uak= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= @@ -405,6 +407,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -427,8 +430,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= -github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f h1:gl1DCiSk+mrXXBGPm6CEeS2MkJuMVzAOrXg34oVj1QI= -github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -441,11 +444,8 @@ github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28 h1:9alfqbr github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= github.com/gostaticanalysis/analysisutil v0.7.1 h1:ZMCjoue3DtDWQ5WyU16YbjbQEQ3VuzwxALrpYd+HeKk= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= @@ -472,6 +472,8 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= @@ -492,9 +494,11 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= -github.com/jhump/protoreflect v1.14.1 h1:N88q7JkxTHWFEqReuTsYH1dPIwXxA0ITNQp7avLY10s= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= github.com/jingyugao/rowserrcheck v1.1.1 h1:zibz55j/MJtLsjP1OF4bSdgXxwL1b+Vn7Tjzq7gFzUs= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= @@ -504,7 +508,6 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= @@ -512,8 +515,8 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.1.0 h1:F78HnrsjY3cR7j0etXy5+TU1Zuy7Xt08X/1aJnH5xXY= github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= -github.com/junk1tm/musttag v0.4.5 h1:d+mpJ1vn6WFEVKHwkgJiIedis1u/EawKOuUTygAUtCo= -github.com/junk1tm/musttag v0.4.5/go.mod h1:XkcL/9O6RmD88JBXb+I15nYRl9W4ExhgQeCBEhfMC8U= +github.com/junk1tm/musttag v0.5.0 h1:bV1DTdi38Hi4pG4OVWa7Kap0hi0o7EczuK6wQt9zPOM= +github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -521,12 +524,12 @@ github.com/kisielk/errcheck v1.6.3 h1:dEKh+GLHcWm2oN34nMvDzn1sqI0i0WxPvrgiJA5JuM github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkHAIKE/contextcheck v1.1.3 h1:l4pNvrb8JSwRd51ojtcOxOeHJzHek+MtOyXbaR0uvmw= -github.com/kkHAIKE/contextcheck v1.1.3/go.mod h1:PG/cwd6c0705/LM0KTr1acO2gORUxkSVWyLJOFW5qoo= +github.com/kkHAIKE/contextcheck v1.1.4 h1:B6zAaLhOEEcjvUgIYEqystmnFk1Oemn8bvJhbt0GMb8= +github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -535,7 +538,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -563,10 +566,10 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/maratori/testableexamples v1.0.0 h1:dU5alXRrD8WKSjOUnmJZuzdxWOEQ57+7s93SLMxb2vI= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= -github.com/maratori/testpackage v1.1.0 h1:GJY4wlzQhuBusMF1oahQCBtUV/AQ/k69IZ68vxaac2Q= -github.com/maratori/testpackage v1.1.0/go.mod h1:PeAhzU8qkCwdGEMTEupsHJNlQu2gZopMC6RjbhmHeDc= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= -github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1rNTU04= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 h1:gWg6ZQ4JhDfJPqlo2srm/LN17lpybq15AryXIRcWYLE= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= @@ -585,8 +588,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/revive v1.2.5 h1:UF9AR8pOAuwNmhXj2odp4mxv9Nx2qUIwVz8ZsU+Mbec= -github.com/mgechev/revive v1.2.5/go.mod h1:nFOXent79jMTISAfOAasKfy0Z2Ejq0WX7Qn/KAdYopI= +github.com/mgechev/revive v1.3.1 h1:OlQkcH40IB2cGuprTPcjB0iIUddgVZgGmDX3IAMR8D4= +github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -594,18 +597,17 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 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/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/moricho/tparallel v0.2.1 h1:95FytivzT6rYzdJLdtfn6m1bfFJylOJK41+lgv/EHf4= -github.com/moricho/tparallel v0.2.1/go.mod h1:fXEIZxG2vdfl0ZF8b42f5a78EhjjD5mX8qUplsoSU4k= +github.com/moricho/tparallel v0.3.0 h1:8dDx3S3e+jA+xiQXC7O3dvfRTe/J+FYlTDDW01Y7z/Q= +github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= @@ -620,8 +622,8 @@ github.com/nishanths/exhaustive v0.9.5 h1:TzssWan6orBiLYVqewCG8faud9qlFntJE30ACp github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/predeclared v0.2.2 h1:V2EPdZPliZymNAn79T8RkNApBjMmVKh5XRpLm/w98Vk= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= -github.com/nunnatsa/ginkgolinter v0.8.1 h1:/y4o/0hV+ruUHj4xXh89xlFjoaitnI4LnkpuYs02q1c= -github.com/nunnatsa/ginkgolinter v0.8.1/go.mod h1:FYYLtszIdmzCH8XMaMPyxPVXZ7VCaIm55bA+gugx+14= +github.com/nunnatsa/ginkgolinter v0.9.0 h1:Sm0zX5QfjJzkeCjEp+t6d3Ha0jwvoDjleP9XCsrEzOA= +github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae h1:FatpGJD2jmJfhZiFDElaC0QhZUDQnxUeAwTGkfAHN3I= @@ -661,8 +663,8 @@ github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvI github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= -github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI= -github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -681,8 +683,8 @@ github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4 h1:RHHRCZeaNy github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4/go.mod h1:RdR1j20Aj5pB6+fw6Y9Ur7lMHpegTEjY1vc19hEZL40= github.com/pointlander/peg v1.0.1 h1:mgA/GQE8TeS9MdkU6Xn6iEzBmQUQCNuWD7rHCK6Mjs0= github.com/pointlander/peg v1.0.1/go.mod h1:5hsGDQR2oZI4QoWz0/Kdg3VSVEC31iJw/b7WjqCBGRI= -github.com/polyfloyd/go-errorlint v1.1.0 h1:VKoEFg5yxSgJ2yFPVhxW7oGz+f8/OVcuMeNvcPIi6Eg= -github.com/polyfloyd/go-errorlint v1.1.0/go.mod h1:Uss7Bc/izYG0leCMRx3WVlrpqWedSZk7V/FUQW6VJ6U= +github.com/polyfloyd/go-errorlint v1.4.0 h1:b+sQ5HibPIAjEZwtuwU8Wz/u0dMZ7YL+bk+9yWyHVJk= +github.com/polyfloyd/go-errorlint v1.4.0/go.mod h1:qJCkPeBn+0EXkdKTrUCcuFStM2xrDKfxI3MGLXPexUs= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -700,8 +702,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.40.0 h1:Afz7EVRqGg2Mqqf4JuF9vdvp1pi220m55Pi9T2JnO4Q= -github.com/prometheus/common v0.40.0/go.mod h1:L65ZJPSmfn/UBWLQIHV7dBrKFidB/wPlF1y5TlSt9OE= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -713,8 +715,8 @@ github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZy github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOAo= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= -github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 h1:TCg2WBOl980XxGFEZSS6KlBGIV0diGdySzxATTWoqaU= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -723,9 +725,9 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= +github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -772,8 +774,8 @@ github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ys github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa h1:YJfZp12Z3AFhSBeXOlv4BO55RMwPn2NoQeDsrdWnBtY= github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= -github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= -github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4lqBjiZI= +github.com/sonatard/noctx v0.0.2 h1:L7Dz4De2zDQhW8S0t+KUjY0MAQJd6SgVwhzNIc4ok00= +github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= github.com/sourcegraph/go-diff v0.7.0 h1:9uLlrd5T46OXs5qpp8L/MTltk0zikUGi0sNNyCpA8G0= github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= @@ -826,8 +828,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c h1:+aPplBwWcHBo6q9xrfWdMrT9o4kltkmmvpemgIjep/8= github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= -github.com/tdakkota/asciicheck v0.1.1 h1:PKzG7JUTUmVspQTDqtkX9eSiLGossXTybutHwTXuO0A= -github.com/tdakkota/asciicheck v0.1.1/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/tdakkota/asciicheck v0.2.0 h1:o8jvnUANo0qXtnslk2d3nMKTFNlOnJjRrNcj0j9qkHM= +github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= 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/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= @@ -838,10 +840,10 @@ github.com/tetafro/godot v1.4.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e h1:MV6KaVu/hzByHP0UvJ4HcMGE/8a6A4Rggc/0wx2AvJo= github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= -github.com/timonwong/loggercheck v0.9.3 h1:ecACo9fNiHxX4/Bc02rW2+kaJIAMAes7qJ7JKxt0EZI= -github.com/timonwong/loggercheck v0.9.3/go.mod h1:wUqnk9yAOIKtGA39l1KLE9Iz0QiTocu/YZoOf+OzFdw= -github.com/tomarrell/wrapcheck/v2 v2.8.0 h1:qDzbir0xmoE+aNxGCPrn+rUSxAX+nG6vREgbbXAR81I= -github.com/tomarrell/wrapcheck/v2 v2.8.0/go.mod h1:ao7l5p0aOlUNJKI0qVwB4Yjlqutd0IvAB9Rdwyilxvg= +github.com/timonwong/loggercheck v0.9.4 h1:HKKhqrjcVj8sxL7K77beXh0adEm6DLjV/QOGeMXEVi4= +github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= +github.com/tomarrell/wrapcheck/v2 v2.8.1 h1:HxSqDSN0sAt0yJYsrcYVoEeyM4aI9yAm3KQpIXDJRhQ= +github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= github.com/tommy-muehle/go-mnd/v2 v2.5.1 h1:NowYhSdyE/1zwK9QCLeRb6USWdoif80Ie+v+yU8u1Zw= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -853,8 +855,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/uudashr/gocognit v1.0.6 h1:2Cgi6MweCsdB6kpcVQp7EW4U23iBFQWfTXiWlyp842Y= github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= -github.com/vektra/mockery/v2 v2.20.2 h1:Rsmcm5Qp6PT1DpTtt9wsMkLNLwtLcGwIfj1pVe/NwUI= -github.com/vektra/mockery/v2 v2.20.2/go.mod h1:Hqgft+OfXtg81uuEShUWO0fPeigZVa9K13UH3wmwXqg= +github.com/vektra/mockery/v2 v2.23.1 h1:N59FENM2d/gWE6Ns5JPuf9a7jqQWeheGefZqvuvb1dM= +github.com/vektra/mockery/v2 v2.23.1/go.mod h1:Zh3Kv1ckKs6FokhlVLcCu6UTyzfS3M8mpROz1lBNp+w= 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/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= @@ -884,19 +886,20 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/otel v1.12.0 h1:IgfC7kqQrRccIKuB7Cl+SRUmsKbEwSGPr0Eu+/ht1SQ= -go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= -go.opentelemetry.io/otel/sdk v1.12.0 h1:8npliVYV7qc0t1FKdpU08eMnOjgPFMnriPhn0HH4q3o= -go.opentelemetry.io/otel/sdk v1.12.0/go.mod h1:WYcvtgquYvgODEvxOry5owO2y9MyciW7JqMz6cpXShE= -go.opentelemetry.io/otel/trace v1.12.0 h1:p28in++7Kd0r2d8gSt931O57fdjUyWxkVbESuILAeUc= -go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= +go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -913,9 +916,9 @@ golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -926,11 +929,12 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 h1:BEABXpNXLEz0WxtA+6CQIz2xkg80e+1zrhWyMcq8VzE= -golang.org/x/exp v0.0.0-20230131160201-f062dba9d201/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s= +golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9 h1:6WHiuFL9FNjg8RljAaT7FNUuKDbvMqS1i5cr2OE2sLQ= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2 h1:J74nGeMgeFnYQJN59eFwh06jX/V8g0lB7LWpjSLxtgU= +golang.org/x/exp/typeparams v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= 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= @@ -960,8 +964,9 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1009,8 +1014,10 @@ golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 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= @@ -1118,8 +1125,9 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1127,8 +1135,9 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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= @@ -1140,8 +1149,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1150,9 +1160,7 @@ golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1175,7 +1183,6 @@ golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1188,19 +1195,16 @@ golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200831203904-5a2aa26beb65/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1223,8 +1227,9 @@ golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1326,8 +1331,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= -google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -1365,8 +1370,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.4.2 h1:6qXr+R5w+ktL5UkwEbPp+fEvfyoMPche6GkOpGHZcLc= -honnef.co/go/tools v0.4.2/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +honnef.co/go/tools v0.4.3 h1:o/n5/K5gXqk8Gozvs2cnL0F2S1/g1vcGCAx2vETjITw= +honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= mvdan.cc/gofumpt v0.4.0 h1:JVf4NN1mIpHogBj7ABpgOyZc65/UUOkKQFkoURsz4MM= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= @@ -1376,5 +1381,6 @@ mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jC mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d h1:3rvTIIM22r9pvXk+q3swxUQAQOxksVMGK7sml4nG57w= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/mempool/clist_mempool.go b/mempool/clist_mempool.go index b0d8c079744..e0501cebb2a 100644 --- a/mempool/clist_mempool.go +++ b/mempool/clist_mempool.go @@ -326,15 +326,11 @@ func (mem *CListMempool) addTx(memTx *mempoolTx) { // Called from: // - Update (lock held) if tx was committed // - resCbRecheck (lock not held) if tx was invalidated -func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement, removeFromCache bool) { +func (mem *CListMempool) removeTx(tx types.Tx, elem *clist.CElement) { mem.txs.Remove(elem) elem.DetachPrev() mem.txsMap.Delete(tx.Key()) atomic.AddInt64(&mem.txsBytes, int64(-len(tx))) - - if removeFromCache { - mem.cache.Remove(tx) - } } // RemoveTxByKey removes a transaction from the mempool by its TxKey index. @@ -342,12 +338,12 @@ func (mem *CListMempool) RemoveTxByKey(txKey types.TxKey) error { if e, ok := mem.txsMap.Load(txKey); ok { memTx := e.(*clist.CElement).Value.(*mempoolTx) if memTx != nil { - mem.removeTx(memTx.tx, e.(*clist.CElement), false) + mem.removeTx(memTx.tx, e.(*clist.CElement)) return nil } - return errors.New("transaction not found") + return errors.New("found empty transaction") } - return errors.New("invalid transaction found") + return errors.New("transaction not found") } func (mem *CListMempool) isFull(txSize int) error { @@ -479,8 +475,11 @@ func (mem *CListMempool) resCbRecheck(req *abci.Request, res *abci.Response) { } else { // Tx became invalidated due to newly committed block. mem.logger.Debug("tx is no longer valid", "tx", types.Tx(tx).Hash(), "res", r, "err", postCheckErr) - // NOTE: we remove tx from the cache because it might be good later - mem.removeTx(tx, mem.recheckCursor, !mem.config.KeepInvalidTxsInCache) + mem.removeTx(tx, mem.recheckCursor) + // We remove the invalid tx from the cache because it might be good later + if !mem.config.KeepInvalidTxsInCache { + mem.cache.Remove(tx) + } } if mem.recheckCursor == mem.recheckEnd { mem.recheckCursor = nil @@ -616,8 +615,8 @@ func (mem *CListMempool) Update( // Mempool after: // 100 // https://github.com/tendermint/tendermint/issues/3322. - if e, ok := mem.txsMap.Load(tx.Key()); ok { - mem.removeTx(tx, e.(*clist.CElement), false) + if err := mem.RemoveTxByKey(tx.Key()); err != nil { + mem.logger.Error("Committed transaction could not be removed from mempool", "key", tx.Key(), err.Error()) } } diff --git a/mempool/ids.go b/mempool/ids.go index d64a07bdaad..aad98b7a7d1 100644 --- a/mempool/ids.go +++ b/mempool/ids.go @@ -1,3 +1,71 @@ package mempool -// These functions were moved into v0/reactor.go and v1/reactor.go +import ( + "fmt" + + cmtsync "github.com/cometbft/cometbft/libs/sync" + "github.com/cometbft/cometbft/p2p" +) + +type mempoolIDs struct { + mtx cmtsync.RWMutex + peerMap map[p2p.ID]uint16 + nextID uint16 // assumes that a node will never have over 65536 active peers + activeIDs map[uint16]struct{} // used to check if a given peerID key is used, the value doesn't matter +} + +// Reserve searches for the next unused ID and assigns it to the +// peer. +func (ids *mempoolIDs) ReserveForPeer(peer p2p.Peer) { + ids.mtx.Lock() + defer ids.mtx.Unlock() + + curID := ids.nextPeerID() + ids.peerMap[peer.ID()] = curID + ids.activeIDs[curID] = struct{}{} +} + +// nextPeerID returns the next unused peer ID to use. +// This assumes that ids's mutex is already locked. +func (ids *mempoolIDs) nextPeerID() uint16 { + if len(ids.activeIDs) == MaxActiveIDs { + panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", MaxActiveIDs)) + } + + _, idExists := ids.activeIDs[ids.nextID] + for idExists { + ids.nextID++ + _, idExists = ids.activeIDs[ids.nextID] + } + curID := ids.nextID + ids.nextID++ + return curID +} + +// Reclaim returns the ID reserved for the peer back to unused pool. +func (ids *mempoolIDs) Reclaim(peer p2p.Peer) { + ids.mtx.Lock() + defer ids.mtx.Unlock() + + removedID, ok := ids.peerMap[peer.ID()] + if ok { + delete(ids.activeIDs, removedID) + delete(ids.peerMap, peer.ID()) + } +} + +// GetForPeer returns an ID reserved for the peer. +func (ids *mempoolIDs) GetForPeer(peer p2p.Peer) uint16 { + ids.mtx.RLock() + defer ids.mtx.RUnlock() + + return ids.peerMap[peer.ID()] +} + +func newMempoolIDs() *mempoolIDs { + return &mempoolIDs{ + peerMap: make(map[p2p.ID]uint16), + activeIDs: map[uint16]struct{}{0: {}}, + nextID: 1, // reserve unknownPeerID(0) for mempoolReactor.BroadcastTx + } +} diff --git a/mempool/ids_test.go b/mempool/ids_test.go index 11d69177de5..c822dd84191 100644 --- a/mempool/ids_test.go +++ b/mempool/ids_test.go @@ -1,23 +1,42 @@ package mempool -// import ( -// "testing" +import ( + "net" + "testing" -// "github.com/stretchr/testify/require" -// "github.com/cometbft/cometbft/types" -// ) + "github.com/cometbft/cometbft/p2p/mock" + "github.com/stretchr/testify/assert" +) -// func TestMempoolIDsBasic(t *testing.T) { -// ids := NewMempoolIDs() +func TestMempoolIDsBasic(t *testing.T) { + ids := newMempoolIDs() -// peerID, err := types.NewNodeID("0011223344556677889900112233445566778899") -// require.NoError(t, err) + peer := mock.NewPeer(net.IP{127, 0, 0, 1}) -// ids.ReserveForPeer(peerID) -// require.EqualValues(t, 1, ids.GetForPeer(peerID)) -// ids.Reclaim(peerID) + ids.ReserveForPeer(peer) + assert.EqualValues(t, 1, ids.GetForPeer(peer)) + ids.Reclaim(peer) -// ids.ReserveForPeer(peerID) -// require.EqualValues(t, 2, ids.GetForPeer(peerID)) -// ids.Reclaim(peerID) -// } + ids.ReserveForPeer(peer) + assert.EqualValues(t, 2, ids.GetForPeer(peer)) + ids.Reclaim(peer) +} + +func TestMempoolIDsPanicsIfNodeRequestsOvermaxActiveIDs(t *testing.T) { + if testing.Short() { + return + } + + // 0 is already reserved for UnknownPeerID + ids := newMempoolIDs() + + for i := 0; i < MaxActiveIDs-1; i++ { + peer := mock.NewPeer(net.IP{127, 0, 0, 1}) + ids.ReserveForPeer(peer) + } + + assert.Panics(t, func() { + peer := mock.NewPeer(net.IP{127, 0, 0, 1}) + ids.ReserveForPeer(peer) + }) +} diff --git a/mempool/reactor.go b/mempool/reactor.go index ae6b2522029..9306e1d0f1d 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -8,7 +8,6 @@ import ( cfg "github.com/cometbft/cometbft/config" "github.com/cometbft/cometbft/libs/clist" "github.com/cometbft/cometbft/libs/log" - cmtsync "github.com/cometbft/cometbft/libs/sync" "github.com/cometbft/cometbft/p2p" protomem "github.com/cometbft/cometbft/proto/tendermint/mempool" "github.com/cometbft/cometbft/types" @@ -24,69 +23,6 @@ type Reactor struct { ids *mempoolIDs } -type mempoolIDs struct { - mtx cmtsync.RWMutex - peerMap map[p2p.ID]uint16 - nextID uint16 // assumes that a node will never have over 65536 active peers - activeIDs map[uint16]struct{} // used to check if a given peerID key is used, the value doesn't matter -} - -// Reserve searches for the next unused ID and assigns it to the -// peer. -func (ids *mempoolIDs) ReserveForPeer(peer p2p.Peer) { - ids.mtx.Lock() - defer ids.mtx.Unlock() - - curID := ids.nextPeerID() - ids.peerMap[peer.ID()] = curID - ids.activeIDs[curID] = struct{}{} -} - -// nextPeerID returns the next unused peer ID to use. -// This assumes that ids's mutex is already locked. -func (ids *mempoolIDs) nextPeerID() uint16 { - if len(ids.activeIDs) == MaxActiveIDs { - panic(fmt.Sprintf("node has maximum %d active IDs and wanted to get one more", MaxActiveIDs)) - } - - _, idExists := ids.activeIDs[ids.nextID] - for idExists { - ids.nextID++ - _, idExists = ids.activeIDs[ids.nextID] - } - curID := ids.nextID - ids.nextID++ - return curID -} - -// Reclaim returns the ID reserved for the peer back to unused pool. -func (ids *mempoolIDs) Reclaim(peer p2p.Peer) { - ids.mtx.Lock() - defer ids.mtx.Unlock() - - removedID, ok := ids.peerMap[peer.ID()] - if ok { - delete(ids.activeIDs, removedID) - delete(ids.peerMap, peer.ID()) - } -} - -// GetForPeer returns an ID reserved for the peer. -func (ids *mempoolIDs) GetForPeer(peer p2p.Peer) uint16 { - ids.mtx.RLock() - defer ids.mtx.RUnlock() - - return ids.peerMap[peer.ID()] -} - -func newMempoolIDs() *mempoolIDs { - return &mempoolIDs{ - peerMap: make(map[p2p.ID]uint16), - activeIDs: map[uint16]struct{}{0: {}}, - nextID: 1, // reserve unknownPeerID(0) for mempoolReactor.BroadcastTx - } -} - // NewReactor returns a new Reactor with the given config and mempool. func NewReactor(config *cfg.MempoolConfig, mempool *CListMempool) *Reactor { memR := &Reactor{ diff --git a/mempool/reactor_test.go b/mempool/reactor_test.go index af458b927e8..6d07e4a09b3 100644 --- a/mempool/reactor_test.go +++ b/mempool/reactor_test.go @@ -3,7 +3,6 @@ package mempool import ( "encoding/hex" "errors" - "net" "sync" "testing" "time" @@ -231,39 +230,6 @@ func TestBroadcastTxForPeerStopsWhenReactorStops(t *testing.T) { leaktest.CheckTimeout(t, 10*time.Second)() } -func TestMempoolIDsBasic(t *testing.T) { - ids := newMempoolIDs() - - peer := mock.NewPeer(net.IP{127, 0, 0, 1}) - - ids.ReserveForPeer(peer) - assert.EqualValues(t, 1, ids.GetForPeer(peer)) - ids.Reclaim(peer) - - ids.ReserveForPeer(peer) - assert.EqualValues(t, 2, ids.GetForPeer(peer)) - ids.Reclaim(peer) -} - -func TestMempoolIDsPanicsIfNodeRequestsOvermaxActiveIDs(t *testing.T) { - if testing.Short() { - return - } - - // 0 is already reserved for UnknownPeerID - ids := newMempoolIDs() - - for i := 0; i < MaxActiveIDs-1; i++ { - peer := mock.NewPeer(net.IP{127, 0, 0, 1}) - ids.ReserveForPeer(peer) - } - - assert.Panics(t, func() { - peer := mock.NewPeer(net.IP{127, 0, 0, 1}) - ids.ReserveForPeer(peer) - }) -} - // TODO: This test tests that we don't panic and are able to generate new // PeerIDs for each peer we add. It seems as though we should be able to test // this in a much more direct way. diff --git a/node/node.go b/node/node.go index 3f963fe5839..7810b0c0997 100644 --- a/node/node.go +++ b/node/node.go @@ -222,7 +222,7 @@ func NewNode(config *cfg.Config, // Determine whether we should do block sync. This must happen after the handshake, since the // app may modify the validator set, specifying ourself as the only validator. - blockSync := config.BlockSyncMode && !onlyValidatorIsUs(state, pubKey) + blockSync := !onlyValidatorIsUs(state, pubKey) logNodeStartupInfo(state, pubKey, logger, consensusLogger) @@ -426,7 +426,7 @@ func (n *Node) OnStart() error { return fmt.Errorf("this blocksync reactor does not support switching from state sync") } err := startStateSync(n.stateSyncReactor, bcR, n.consensusReactor, n.stateSyncProvider, - n.config.StateSync, n.config.BlockSyncMode, n.stateStore, n.blockStore, n.stateSyncGenesis) + n.config.StateSync, n.stateStore, n.blockStore, n.stateSyncGenesis) if err != nil { return fmt.Errorf("failed to start state sync: %w", err) } diff --git a/node/setup.go b/node/setup.go index 5c2d0286769..c118d724bcb 100644 --- a/node/setup.go +++ b/node/setup.go @@ -279,7 +279,7 @@ func createBlocksyncReactor(config *cfg.Config, case "v1", "v2": return nil, fmt.Errorf("block sync version %s has been deprecated. Please use v0", config.BlockSync.Version) default: - return nil, fmt.Errorf("unknown fastsync version %s", config.BlockSync.Version) + return nil, fmt.Errorf("unknown block sync version %s", config.BlockSync.Version) } bcReactor.SetLogger(logger.With("module", "blocksync")) @@ -470,7 +470,7 @@ func createPEXReactorAndAddToSwitch(addrBook pex.AddrBook, config *cfg.Config, // startStateSync starts an asynchronous state sync process, then switches to block sync mode. func startStateSync(ssR *statesync.Reactor, bcR blockSyncReactor, conR *cs.Reactor, - stateProvider statesync.StateProvider, config *cfg.StateSyncConfig, blockSync bool, + stateProvider statesync.StateProvider, config *cfg.StateSyncConfig, stateStore sm.Store, blockStore *store.BlockStore, state sm.State, ) error { ssR.Logger.Info("Starting state sync") @@ -509,14 +509,10 @@ func startStateSync(ssR *statesync.Reactor, bcR blockSyncReactor, conR *cs.React return } - if blockSync { - err = bcR.SwitchToBlockSync(state) - if err != nil { - ssR.Logger.Error("Failed to switch to block sync", "err", err) - return - } - } else { - conR.SwitchToConsensus(state, true) + err = bcR.SwitchToBlockSync(state) + if err != nil { + ssR.Logger.Error("Failed to switch to block sync", "err", err) + return } }() return nil diff --git a/rpc/client/main_test.go b/rpc/client/main_test.go index 11896673540..290ebf35e31 100644 --- a/rpc/client/main_test.go +++ b/rpc/client/main_test.go @@ -19,6 +19,8 @@ func TestMain(m *testing.M) { } app := kvstore.NewPersistentApplication(dir) + // If testing block event generation + // app.SetGenBlockEvents() needs to be called here node = rpctest.StartTendermint(app) code := m.Run() diff --git a/rpc/client/rpc_test.go b/rpc/client/rpc_test.go index 02db04bcc4e..f9cc2f3d19c 100644 --- a/rpc/client/rpc_test.go +++ b/rpc/client/rpc_test.go @@ -516,6 +516,27 @@ func TestTxSearchWithTimeout(t *testing.T) { require.Greater(t, len(result.Txs), 0, "expected a lot of transactions") } +// This test does nothing if we do not call app.SetGenBlockEvents() within main_test.go +// It will nevertheless pass as there are no events being generated. +func TestBlockSearch(t *testing.T) { + c := getHTTPClient() + + // first we broadcast a few txs + for i := 0; i < 10; i++ { + _, _, tx := MakeTxKV() + + _, err := c.BroadcastTxCommit(context.Background(), tx) + require.NoError(t, err) + } + require.NoError(t, client.WaitForHeight(c, 5, nil)) + // This cannot test match_events as it calls the client BlockSearch function directly + // It is the RPC request handler that processes the match_event + result, err := c.BlockSearch(context.Background(), "begin_event.foo = 100 AND begin_event.bar = 300", nil, nil, "asc") + require.NoError(t, err) + blockCount := len(result.Blocks) + require.Equal(t, blockCount, 0) + +} func TestTxSearch(t *testing.T) { c := getHTTPClient() @@ -536,8 +557,7 @@ func TestTxSearch(t *testing.T) { find := result.Txs[len(result.Txs)-1] anotherTxHash := types.Tx("a different tx").Hash() - for i, c := range GetClients() { - t.Logf("client %d", i) + for _, c := range GetClients() { // now we query for the tx. result, err := c.TxSearch(context.Background(), fmt.Sprintf("tx.hash='%v'", find.Hash), true, nil, nil, "asc") @@ -616,16 +636,17 @@ func TestTxSearch(t *testing.T) { pages = int(math.Ceil(float64(txCount) / float64(perPage))) ) + totalTx := 0 for page := 1; page <= pages; page++ { page := page - result, err := c.TxSearch(context.Background(), "tx.height >= 1", false, &page, &perPage, "asc") + result, err := c.TxSearch(context.Background(), "tx.height >= 1", true, &page, &perPage, "asc") require.NoError(t, err) if page < pages { require.Len(t, result.Txs, perPage) } else { require.LessOrEqual(t, len(result.Txs), perPage) } - require.Equal(t, txCount, result.TotalCount) + totalTx = totalTx + len(result.Txs) for _, tx := range result.Txs { require.False(t, seen[tx.Height], "Found duplicate height %v in page %v", tx.Height, page) @@ -635,6 +656,7 @@ func TestTxSearch(t *testing.T) { maxHeight = tx.Height } } + require.Equal(t, txCount, totalTx) require.Len(t, seen, txCount) } } diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index 4f99f72afec..b39c090ff3e 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -61,7 +61,7 @@ func (env *Environment) DumpConsensusState(ctx *rpctypes.Context) (*ctypes.Resul if !ok { // peer does not have a state yet continue } - peerStateJSON, err := peerState.ToJSON() + peerStateJSON, err := peerState.MarshalJSON() if err != nil { return nil, err } diff --git a/rpc/openapi/openapi.yaml b/rpc/openapi/openapi.yaml index 97ebd7fb90b..b0705576857 100644 --- a/rpc/openapi/openapi.yaml +++ b/rpc/openapi/openapi.yaml @@ -2,8 +2,8 @@ openapi: 3.0.0 info: title: CometBFT RPC contact: - name: CometBFT RPC - url: https://github.com/cometbft/cometbft/issues/new/choose + name: CometBFT + url: https://cometbft.com/ description: | CometBFT supports the following RPC protocols: @@ -17,12 +17,22 @@ info: `$CMTHOME/config/config.toml` file or by using the `--rpc.X` command-line flags. - Default rpc listen address is `tcp://0.0.0.0:26657`. + The default RPC listen address is `tcp://127.0.0.1:26657`. To set another address, set the `laddr` config parameter to desired value. CORS (Cross-Origin Resource Sharing) can be enabled by setting `cors_allowed_origins`, `cors_allowed_methods`, `cors_allowed_headers` config parameters. + If testing using a local RPC node, under the `[rpc]` + section change the `cors_allowed_origins` property, please add the URL of + the site where this OpenAPI document is running, for example: + + `cors_allowed_origins = ["http://localhost:8088"]` + + or if testing from the official documentation site: + + `cors_allowed_origins = ["https://docs.cometbft.com"]` + ## Arguments Arguments which expect strings or byte arrays may be passed as quoted @@ -47,22 +57,21 @@ info: Asynchronous RPC functions like event `subscribe` and `unsubscribe` are only available via websockets. - Example using https://github.com/hashrocket/ws: + For example using the [websocat](https://github.com/vi/websocat) tool, you can subscribe for 'NewBlock` events + with the following command: + + echo '{ "jsonrpc": "2.0","method": "subscribe","id": 0,"params": {"query": "tm.event='"'NewBlock'"'"} }' | websocat -n -t ws://127.0.0.1:26657/websocket - ws ws://localhost:26657/websocket - > { "jsonrpc": "2.0", "method": "subscribe", "params": ["tm.event='NewBlock'"], "id": 1 } version: "main" license: name: Apache 2.0 url: https://github.com/cometbft/cometbft/blob/main/LICENSE servers: - - url: https://rpc.cosmos.network - description: Cosmos mainnet node to interact with the CometBFT RPC + - url: https://rpc.cosmos.directory/cosmoshub + description: Interact with the CometBFT RPC from a public node in the Cosmos registry - url: http://localhost:26657 - description: Interact with the CometBFT RPC locally on your device + description: Interact with CometBFT RPC node running locally tags: - - name: Websocket - description: Subscribe/unsubscribe are reserved for websocket events. - name: Info description: Informations about the node APIs - name: Tx @@ -94,9 +103,9 @@ paths: (https://github.com/tendermint/tendermint/issues/3322) - Please refer to - https://docs.cometbft.com/main/core/using-cometbft.html#formatting - for formatting/encoding rules. + Please refer to [formatting/encoding rules](https://docs.cometbft.com/main/core/using-cometbft.html#formatting) + for additional details + parameters: - in: query name: tx @@ -138,9 +147,9 @@ paths: (https://github.com/tendermint/tendermint/issues/3322) 3. node can be offline - Please refer to - https://docs.cometbft.com/main/core/using-cometbft.html#formatting - for formatting/encoding rules. + Please refer to [formatting/encoding rules](https://docs.cometbft.com/main/core/using-cometbft.html#formatting) + for additional details + parameters: - in: query name: tx @@ -180,9 +189,9 @@ paths: If CheckTx or DeliverTx fail, no error will be returned, but the returned result will contain a non-OK ABCI code. - Please refer to - https://docs.cometbft.com/main/core/using-cometbft.html#formatting - for formatting/encoding rules. + Please refer to [formatting/encoding rules](https://docs.cometbft.com/main/core/using-cometbft.html#formatting) + for additional details + parameters: - in: query name: tx @@ -213,9 +222,8 @@ paths: description: | The transaction won't be added to the mempool. - Please refer to - https://docs.cometbft.com/main/core/using-cometbft.html#formatting - for formatting/encoding rules. + Please refer to [formatting/encoding rules](https://docs.cometbft.com/main/core/using-cometbft.html#formatting) + for additional details Upon success, the `Cache-Control` header will be set with the default maximum age. @@ -240,225 +248,6 @@ paths: application/json: schema: $ref: "#/components/schemas/ErrorResponse" - /subscribe: - get: - summary: Subscribe for events via WebSocket. - tags: - - Websocket - operationId: subscribe - description: | - To tell which events you want, you need to provide a query. query is a - string, which has a form: "condition AND condition ..." (no OR at the - moment). condition has a form: "key operation operand". key is a string with - a restricted set of possible symbols ( \t\n\r\\()"'=>< are not allowed). - operation can be "=", "<", "<=", ">", ">=", "CONTAINS" AND "EXISTS". operand - can be a string (escaped with single quotes), number, date or time. - - Examples: - tm.event = 'NewBlock' # new blocks - tm.event = 'CompleteProposal' # node got a complete proposal - tm.event = 'Tx' AND tx.hash = 'XYZ' # single transaction - tm.event = 'Tx' AND tx.height = 5 # all txs of the fifth block - tx.height = 5 # all txs of the fifth block - - CometBFT provides a few predefined keys: tm.event, tx.hash and tx.height. - Note for transactions, you can define additional keys by providing events with - DeliverTx response. - - import ( - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/libs/pubsub/query" - ) - - abci.ResponseDeliverTx{ - Events: []abci.Event{ - { - Type: "rewards.withdraw", - Attributes: abci.EventAttribute{ - {Key: []byte("address"), Value: []byte("AddrA"), Index: true}, - {Key: []byte("source"), Value: []byte("SrcX"), Index: true}, - {Key: []byte("amount"), Value: []byte("..."), Index: true}, - {Key: []byte("balance"), Value: []byte("..."), Index: true}, - }, - }, - { - Type: "rewards.withdraw", - Attributes: abci.EventAttribute{ - {Key: []byte("address"), Value: []byte("AddrB"), Index: true}, - {Key: []byte("source"), Value: []byte("SrcY"), Index: true}, - {Key: []byte("amount"), Value: []byte("..."), Index: true}, - {Key: []byte("balance"), Value: []byte("..."), Index: true}, - }, - }, - { - Type: "transfer", - Attributes: abci.EventAttribute{ - {Key: []byte("sender"), Value: []byte("AddrC"), Index: true}, - {Key: []byte("recipient"), Value: []byte("AddrD"), Index: true}, - {Key: []byte("amount"), Value: []byte("..."), Index: true}, - }, - }, - }, - } - - All events are indexed by a composite key of the form {eventType}.{evenAttrKey}. - In the above examples, the following keys would be indexed: - - rewards.withdraw.address - - rewards.withdraw.source - - rewards.withdraw.amount - - rewards.withdraw.balance - - transfer.sender - - transfer.recipient - - transfer.amount - - Multiple event types with duplicate keys are allowed and are meant to - categorize unique and distinct events. In the above example, all events - indexed under the key `rewards.withdraw.address` will have the following - values stored and queryable: - - - AddrA - - AddrB - - To create a query for txs where address AddrA withdrew rewards: - query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA'") - - To create a query for txs where address AddrA withdrew rewards from source Y: - query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA' AND rewards.withdraw.source = 'Y'") - - To create a query for txs where AddrA transferred funds: - query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrA'") - - The following queries would return no results: - query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrZ'") - query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrZ'") - query.MustParse("tm.event = 'Tx' AND rewards.withdraw.source = 'W'") - - See list of all possible events here - https://godoc.org/github.com/cometbft/cometbft/types#pkg-constants - - For complete query syntax, check out - https://godoc.org/github.com/cometbft/cometbft/libs/pubsub/query. - - ```go - import rpchttp "github.com/cometbft/rpc/client/http" - import "github.com/cometbft/cometbft/types" - - client := rpchttp.New("tcp:0.0.0.0:26657", "/websocket") - err := client.Start() - if err != nil { - handle error - } - defer client.Stop() - ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second) - defer cancel() - query := "tm.event = 'Tx' AND tx.height = 3" - txs, err := client.Subscribe(ctx, "test-client", query) - if err != nil { - handle error - } - - go func() { - for e := range txs { - fmt.Println("got ", e.Data.(types.EventDataTx)) - } - }() - ``` - - NOTE: if you're not reading events fast enough, CometBFT might - terminate the subscription. - parameters: - - in: query - name: query - required: true - schema: - type: string - example: tm.event = 'Tx' AND tx.height = 5 - description: | - query is a string, which has a form: "condition AND condition ..." (no OR at the - moment). condition has a form: "key operation operand". key is a string with - a restricted set of possible symbols ( \t\n\r\\()"'=>< are not allowed). - operation can be "=", "<", "<=", ">", ">=", "CONTAINS". operand can be a - string (escaped with single quotes), number, date or time. - responses: - "200": - description: empty answer - content: - application/json: - schema: - $ref: "#/components/schemas/EmptyResponse" - "500": - description: empty error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - /unsubscribe: - get: - summary: Unsubscribe from event on Websocket - tags: - - Websocket - operationId: unsubscribe - description: | - ```go - client := rpchttp.New("tcp:0.0.0.0:26657", "/websocket") - err := client.Start() - if err != nil { - handle error - } - defer client.Stop() - query := "tm.event = 'Tx' AND tx.height = 3" - err = client.Unsubscribe(context.Background(), "test-client", query) - if err != nil { - handle error - } - ``` - parameters: - - in: query - name: query - required: true - schema: - type: string - example: tm.event = 'Tx' AND tx.height = 5 - description: | - query is a string, which has a form: "condition AND condition ..." (no OR at the - moment). condition has a form: "key operation operand". key is a string with - a restricted set of possible symbols ( \t\n\r\\()"'=>< are not allowed). - operation can be "=", "<", "<=", ">", ">=", "CONTAINS". operand can be a - string (escaped with single quotes), number, date or time. - responses: - "200": - description: Answer - content: - application/json: - schema: - $ref: "#/components/schemas/EmptyResponse" - "500": - description: Error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" - /unsubscribe_all: - get: - summary: Unsubscribe from all events via WebSocket - tags: - - Websocket - operationId: unsubscribe_all - description: | - Unsubscribe from all events via WebSocket - responses: - "200": - description: empty answer - content: - application/json: - schema: - $ref: "#/components/schemas/EmptyResponse" - "500": - description: empty error - content: - application/json: - schema: - $ref: "#/components/schemas/ErrorResponse" /health: get: summary: Node heartbeat diff --git a/spec/README.md b/spec/README.md index ebb7f210d56..921c68b7cb0 100644 --- a/spec/README.md +++ b/spec/README.md @@ -60,11 +60,11 @@ hash-linked batches of transactions. Such transaction batches are called "blocks Hence, CometBFT defines a "blockchain". Each block in CometBFT has a unique index - its Height. -Height's in the blockchain are monotonic. +Heights in the blockchain are monotonic. Each block is committed by a known set of weighted Validators. Membership and weighting within this validator set may change over time. CometBFT guarantees the safety and liveness of the blockchain -so long as less than 1/3 of the total weight of the Validator set +as long as less than 1/3 of the total weight of the Validator set is malicious or faulty. A commit in CometBFT is a set of signed messages from more than 2/3 of diff --git a/spec/core/data_structures.md b/spec/core/data_structures.md index 4bb59c25c69..a5be15626b4 100644 --- a/spec/core/data_structures.md +++ b/spec/core/data_structures.md @@ -71,7 +71,7 @@ and `ABCIApp` is an ABCI application that can return results and changes to the set (TODO). Execute is defined as: ```go -func Execute(s State, app ABCIApp, block Block) State { +func Execute(state State, app ABCIApp, block Block) State { // Fuction ApplyBlock executes block of transactions against the app and returns the new root hash of the app state, // modifications to the validator set and the changes of the consensus parameters. AppHash, ValidatorChanges, ConsensusParamChanges := app.ApplyBlock(block) @@ -82,7 +82,6 @@ func Execute(s State, app ABCIApp, block Block) State { InitialHeight: state.InitialHeight, LastResults: abciResponses.DeliverTxResults, AppHash: AppHash, - InitialHeight: state.InitialHeight, LastValidators: state.Validators, Validators: state.NextValidators, NextValidators: UpdateValidators(state.NextValidators, ValidatorChanges), diff --git a/state/execution.go b/state/execution.go index 9b1acb08cca..5c4aecdc7b7 100644 --- a/state/execution.go +++ b/state/execution.go @@ -165,7 +165,7 @@ func (blockExec *BlockExecutor) ProcessProposal( NextValidatorsHash: block.NextValidatorsHash, }) if err != nil { - return false, ErrInvalidBlock(err) + return false, err } if resp.IsStatusUnknown() { panic(fmt.Sprintf("ProcessProposal responded with status %s", resp.Status.String())) diff --git a/state/indexer/block/kv/kv.go b/state/indexer/block/kv/kv.go index 854df5d3717..6128bd37fc5 100644 --- a/state/indexer/block/kv/kv.go +++ b/state/indexer/block/kv/kv.go @@ -1,6 +1,7 @@ package kv import ( + "bytes" "context" "errors" "fmt" @@ -26,6 +27,10 @@ var _ indexer.BlockIndexer = (*BlockerIndexer)(nil) // such that matching search criteria returns the respective block height(s). type BlockerIndexer struct { store dbm.DB + + // Add unique event identifier to use when querying + // Matching will be done both on height AND eventSeq + eventSeq int64 } func New(store dbm.DB) *BlockerIndexer { @@ -49,7 +54,7 @@ func (idx *BlockerIndexer) Has(height int64) (bool, error) { // The following is indexed: // // primary key: encode(block.height | height) => encode(height) -// FinalizeBlock events: encode(eventType.eventAttr|eventValue|height|finalize_block) => encode(height) +// FinalizeBlock events: encode(eventType.eventAttr|eventValue|height|finalize_block|eventSeq) => encode(height) func (idx *BlockerIndexer) Index(bh types.EventDataNewBlockEvents) error { batch := idx.store.NewBatch() defer batch.Close() @@ -89,17 +94,35 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, conditions := q.Syntax() - // If there is an exact height query, return the result immediately - // (if it exists). - height, ok := lookForHeight(conditions) - if ok { - ok, err := idx.Has(height) + // conditions to skip because they're handled before "everything else" + skipIndexes := make([]int, 0) + + var ok bool + + var heightInfo HeightInfo + // If we are not matching events and block.height occurs more than once, the later value will + // overwrite the first one. + conditions, heightInfo, ok = dedupHeight(conditions) + + // Extract ranges. If both upper and lower bounds exist, it's better to get + // them in order as to not iterate over kvs that are not within range. + ranges, rangeIndexes, heightRange := indexer.LookForRangesWithHeight(conditions) + heightInfo.heightRange = heightRange + + // If we have additional constraints and want to query per event + // attributes, we cannot simply return all blocks for a height. + // But we remember the height we want to find and forward it to + // match(). If we only have the height constraint + // in the query (the second part of the ||), we don't need to query + // per event conditions and return all events within the height range. + if ok && heightInfo.onlyHeightEq { + ok, err := idx.Has(heightInfo.height) if err != nil { return nil, err } if ok { - return []int64{height}, nil + return []int64{heightInfo.height}, nil } return results, nil @@ -107,24 +130,34 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, var heightsInitialized bool filteredHeights := make(map[string][]byte) + if heightInfo.heightEqIdx != -1 { + skipIndexes = append(skipIndexes, heightInfo.heightEqIdx) + } - // conditions to skip because they're handled before "everything else" - skipIndexes := make([]int, 0) - - // Extract ranges. If both upper and lower bounds exist, it's better to get - // them in order as to not iterate over kvs that are not within range. - ranges, rangeIndexes := indexer.LookForRanges(conditions) if len(ranges) > 0 { skipIndexes = append(skipIndexes, rangeIndexes...) for _, qr := range ranges { + // If we have a query range over height and want to still look for + // specific event values we do not want to simply return all + // blocks in this height range. We remember the height range info + // and pass it on to match() to take into account when processing events. + if qr.Key == types.BlockHeightKey && !heightInfo.onlyHeightRange { + // If the query contains ranges other than the height then we need to treat the height + // range when querying the conditions of the other range. + // Otherwise we can just return all the blocks within the height range (as there is no + // additional constraint on events) + + continue + + } prefix, err := orderedcode.Append(nil, qr.Key) if err != nil { return nil, fmt.Errorf("failed to create prefix key: %w", err) } if !heightsInitialized { - filteredHeights, err = idx.matchRange(ctx, qr, prefix, filteredHeights, true) + filteredHeights, err = idx.matchRange(ctx, qr, prefix, filteredHeights, true, heightInfo) if err != nil { return nil, err } @@ -137,7 +170,7 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, break } } else { - filteredHeights, err = idx.matchRange(ctx, qr, prefix, filteredHeights, false) + filteredHeights, err = idx.matchRange(ctx, qr, prefix, filteredHeights, false, heightInfo) if err != nil { return nil, err } @@ -157,7 +190,7 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, } if !heightsInitialized { - filteredHeights, err = idx.match(ctx, c, startKey, filteredHeights, true) + filteredHeights, err = idx.match(ctx, c, startKey, filteredHeights, true, heightInfo) if err != nil { return nil, err } @@ -170,7 +203,7 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, break } } else { - filteredHeights, err = idx.match(ctx, c, startKey, filteredHeights, false) + filteredHeights, err = idx.match(ctx, c, startKey, filteredHeights, false, heightInfo) if err != nil { return nil, err } @@ -179,6 +212,7 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, // fetch matching heights results = make([]int64, 0, len(filteredHeights)) + resultMap := make(map[int64]struct{}) for _, hBz := range filteredHeights { h := int64FromBytes(hBz) @@ -187,7 +221,10 @@ func (idx *BlockerIndexer) Search(ctx context.Context, q *query.Query) ([]int64, return nil, err } if ok { - results = append(results, h) + if _, ok := resultMap[h]; !ok { + resultMap[h] = struct{}{} + results = append(results, h) + } } select { @@ -215,6 +252,7 @@ func (idx *BlockerIndexer) matchRange( startKey []byte, filteredHeights map[string][]byte, firstRun bool, + heightInfo HeightInfo, ) (map[string][]byte, error) { // A previous match was attempted but resulted in no matches, so we return // no matches (assuming AND operand). @@ -223,8 +261,6 @@ func (idx *BlockerIndexer) matchRange( } tmpHeights := make(map[string][]byte) - lowerBound := qr.LowerBoundValue() - upperBound := qr.UpperBoundValue() it, err := dbm.IteratePrefix(idx.store, startKey) if err != nil { @@ -255,17 +291,14 @@ LOOP: continue LOOP } - include := true - if lowerBound != nil && v < lowerBound.(int64) { - include = false - } - - if upperBound != nil && v > upperBound.(int64) { - include = false + if qr.Key != types.BlockHeightKey { + keyHeight, err := parseHeightFromEventKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue LOOP + } } - - if include { - tmpHeights[string(it.Value())] = it.Value() + if checkBounds(qr, v) { + idx.setTmpHeights(tmpHeights, it) } } @@ -294,8 +327,12 @@ LOOP: // Remove/reduce matches in filteredHashes that were not found in this // match (tmpHashes). - for k := range filteredHeights { - if tmpHeights[k] == nil { + for k, v := range filteredHeights { + tmpHeight := tmpHeights[k] + + // Check whether in this iteration we have not found an overlapping height (tmpHeight == nil) + // or whether the events in which the attributed occurred do not match (first part of the condition) + if tmpHeight == nil || !bytes.Equal(tmpHeight, v) { delete(filteredHeights, k) select { @@ -310,6 +347,30 @@ LOOP: return filteredHeights, nil } +func (idx *BlockerIndexer) setTmpHeights(tmpHeights map[string][]byte, it dbm.Iterator) { + // If we return attributes that occur within the same events, then store the event sequence in the + // result map as well + eventSeq, _ := parseEventSeqFromEventKey(it.Key()) + retVal := it.Value() + tmpHeights[string(retVal)+strconv.FormatInt(eventSeq, 10)] = it.Value() + +} + +func checkBounds(ranges indexer.QueryRange, v int64) bool { + include := true + lowerBound := ranges.LowerBoundValue() + upperBound := ranges.UpperBoundValue() + if lowerBound != nil && v < lowerBound.(int64) { + include = false + } + + if upperBound != nil && v > upperBound.(int64) { + include = false + } + + return include +} + // match returns all matching heights that meet a given query condition and start // key. An already filtered result (filteredHeights) is provided such that any // non-intersecting matches are removed. @@ -322,6 +383,7 @@ func (idx *BlockerIndexer) match( startKeyBz []byte, filteredHeights map[string][]byte, firstRun bool, + heightInfo HeightInfo, ) (map[string][]byte, error) { // A previous match was attempted but resulted in no matches, so we return // no matches (assuming AND operand). @@ -340,7 +402,13 @@ func (idx *BlockerIndexer) match( defer it.Close() for ; it.Valid(); it.Next() { - tmpHeights[string(it.Value())] = it.Value() + + keyHeight, err := parseHeightFromEventKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + + idx.setTmpHeights(tmpHeights, it) if err := ctx.Err(); err != nil { break @@ -364,7 +432,11 @@ func (idx *BlockerIndexer) match( defer it.Close() for ; it.Valid(); it.Next() { - tmpHeights[string(it.Value())] = it.Value() + keyHeight, err := parseHeightFromEventKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + idx.setTmpHeights(tmpHeights, it) select { case <-ctx.Done(): @@ -397,7 +469,11 @@ func (idx *BlockerIndexer) match( } if strings.Contains(eventValue, c.Arg.Value()) { - tmpHeights[string(it.Value())] = it.Value() + keyHeight, err := parseHeightFromEventKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + idx.setTmpHeights(tmpHeights, it) } select { @@ -428,8 +504,9 @@ func (idx *BlockerIndexer) match( // Remove/reduce matches in filteredHeights that were not found in this // match (tmpHeights). - for k := range filteredHeights { - if tmpHeights[k] == nil { + for k, v := range filteredHeights { + tmpHeight := tmpHeights[k] + if tmpHeight == nil || !bytes.Equal(tmpHeight, v) { delete(filteredHeights, k) select { @@ -448,6 +525,7 @@ func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, typ heightBz := int64ToBytes(height) for _, event := range events { + idx.eventSeq = idx.eventSeq + 1 // only index events with a non-empty type if len(event.Type) == 0 { continue @@ -465,7 +543,7 @@ func (idx *BlockerIndexer) indexEvents(batch dbm.Batch, events []abci.Event, typ } if attr.GetIndex() { - key, err := eventKey(compositeKey, typ, attr.Value, height) + key, err := eventKey(compositeKey, typ, attr.Value, height, idx.eventSeq) if err != nil { return fmt.Errorf("failed to create block index key: %w", err) } diff --git a/state/indexer/block/kv/kv_test.go b/state/indexer/block/kv/kv_test.go index 1311131d4b8..e28cf6ec02a 100644 --- a/state/indexer/block/kv/kv_test.go +++ b/state/indexer/block/kv/kv_test.go @@ -110,6 +110,14 @@ func TestBlockIndexer(t *testing.T) { q: query.MustCompile(`block.height > 2 AND end_event.foo <= 8`), results: []int64{4, 6, 8}, }, + "end_event.foo > 100": { + q: query.MustCompile("end_event.foo > 100"), + results: []int64{}, + }, + "block.height >= 2 AND end_event.foo < 8": { + q: query.MustCompile("block.height >= 2 AND end_event.foo < 8"), + results: []int64{2, 4, 6}, + }, "begin_event.proposer CONTAINS 'FFFFFFF'": { q: query.MustCompile(`begin_event.proposer CONTAINS 'FFFFFFF'`), results: []int64{}, @@ -118,6 +126,189 @@ func TestBlockIndexer(t *testing.T) { q: query.MustCompile(`begin_event.proposer CONTAINS 'FCAA001'`), results: []int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, }, + "end_event.foo CONTAINS '1'": { + q: query.MustCompile("end_event.foo CONTAINS '1'"), + results: []int64{1, 10}, + }, + } + + for name, tc := range testCases { + tc := tc + t.Run(name, func(t *testing.T) { + results, err := indexer.Search(context.Background(), tc.q) + require.NoError(t, err) + require.Equal(t, tc.results, results) + }) + } +} + +func TestBlockIndexerMulti(t *testing.T) { + store := db.NewPrefixDB(db.NewMemDB(), []byte("block_events")) + indexer := blockidxkv.New(store) + + require.NoError(t, indexer.Index(types.EventDataNewBlockEvents{ + Height: 1, + Events: []abci.Event{ + {}, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: "100", + Index: true, + }, + { + Key: "bar", + Value: "200", + Index: true, + }, + }, + }, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: "300", + Index: true, + }, + { + Key: "bar", + Value: "500", + Index: true, + }, + }, + }, + }, + })) + + require.NoError(t, indexer.Index(types.EventDataNewBlockEvents{ + Height: 2, + Events: []abci.Event{ + {}, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: "100", + Index: true, + }, + { + Key: "bar", + Value: "200", + Index: true, + }, + }, + }, + { + Type: "end_event", + Attributes: []abci.EventAttribute{ + { + Key: "foo", + Value: "300", + Index: true, + }, + { + Key: "bar", + Value: "400", + Index: true, + }, + }, + }, + }, + })) + + testCases := map[string]struct { + q *query.Query + results []int64 + }{ + + "query return all events from a height - exact": { + q: query.MustCompile("block.height = 1"), + results: []int64{1}, + }, + "query return all events from a height - exact - no match.events": { + q: query.MustCompile("block.height = 1"), + results: []int64{1}, + }, + "query return all events from a height - exact (deduplicate height)": { + q: query.MustCompile("block.height = 1 AND block.height = 2"), + results: []int64{1}, + }, + "query return all events from a height - exact (deduplicate height) - no match.events": { + q: query.MustCompile("block.height = 1 AND block.height = 2"), + results: []int64{1}, + }, + "query return all events from a height - range": { + q: query.MustCompile("block.height < 2 AND block.height > 0 AND block.height > 0"), + results: []int64{1}, + }, + "query return all events from a height - range - no match.events": { + q: query.MustCompile("block.height < 2 AND block.height > 0 AND block.height > 0"), + results: []int64{1}, + }, + "query return all events from a height - range 2": { + q: query.MustCompile("block.height < 3 AND block.height < 2 AND block.height > 0 AND block.height > 0"), + results: []int64{1}, + }, + "query return all events from a height - range 3": { + q: query.MustCompile("block.height < 1 AND block.height > 1"), + results: []int64{}, + }, + "query matches fields from same event": { + q: query.MustCompile("end_event.bar < 300 AND end_event.foo = 100 AND block.height > 0 AND block.height <= 2"), + results: []int64{1, 2}, + }, + "query matches fields from same event - no match.events": { + q: query.MustCompile("end_event.bar < 300 AND end_event.foo = 100 AND block.height > 0 AND block.height <= 2"), + results: []int64{1, 2}, + }, + "query matches fields from multiple events": { + q: query.MustCompile("end_event.foo = 100 AND end_event.bar = 400 AND block.height = 2"), + results: []int64{}, + }, + "query matches fields from multiple events 2": { + q: query.MustCompile("end_event.foo = 100 AND end_event.bar > 200 AND block.height > 0 AND block.height < 3"), + results: []int64{}, + }, + "query matches fields from multiple events allowed": { + q: query.MustCompile("end_event.foo = 100 AND end_event.bar = 400"), + results: []int64{}, + }, + "query matches fields from all events whose attribute is within range": { + q: query.MustCompile("block.height = 2 AND end_event.foo < 300"), + results: []int64{2}, + }, + "deduplication test - match.events multiple 2": { + q: query.MustCompile("end_event.foo = 100 AND end_event.bar = 400 AND block.height = 2"), + results: []int64{}, + }, + "query using CONTAINS matches fields from all events whose attribute is within range": { + q: query.MustCompile("block.height = 2 AND end_event.foo CONTAINS '30'"), + results: []int64{2}, + }, + "query matches all fields from multiple events": { + q: query.MustCompile("end_event.bar > 100 AND end_event.bar <= 500"), + results: []int64{1, 2}, + }, + "query matches all fields from multiple events - no match.events": { + q: query.MustCompile("end_event.bar > 100 AND end_event.bar <= 500"), + results: []int64{1, 2}, + }, + "query with height range and height equality - should ignore equality": { + q: query.MustCompile("block.height = 2 AND end_event.foo >= 100 AND block.height < 2"), + results: []int64{1}, + }, + "query with non-existent field": { + q: query.MustCompile("end_event.baz = 100"), + results: []int64{}, + }, + "query with non-existent field ": { + q: query.MustCompile("end_event.baz = 100"), + results: []int64{}, + }, } for name, tc := range testCases { diff --git a/state/indexer/block/kv/util.go b/state/indexer/block/kv/util.go index ce6508befdc..9ccb84720fa 100644 --- a/state/indexer/block/kv/util.go +++ b/state/indexer/block/kv/util.go @@ -8,9 +8,18 @@ import ( "github.com/google/orderedcode" "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/state/indexer" "github.com/cometbft/cometbft/types" ) +type HeightInfo struct { + heightRange indexer.QueryRange + height int64 + heightEqIdx int + onlyHeightRange bool + onlyHeightEq bool +} + func intInSlice(a int, list []int) bool { for _, b := range list { if b == a { @@ -40,13 +49,14 @@ func heightKey(height int64) ([]byte, error) { ) } -func eventKey(compositeKey, typ, eventValue string, height int64) ([]byte, error) { +func eventKey(compositeKey, typ, eventValue string, height int64, eventSeq int64) ([]byte, error) { return orderedcode.Append( nil, compositeKey, eventValue, height, typ, + eventSeq, ) } @@ -74,24 +84,110 @@ func parseValueFromEventKey(key []byte) (string, error) { height int64 ) - remaining, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ) + _, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ) if err != nil { return "", fmt.Errorf("failed to parse event key: %w", err) } + return eventValue, nil +} + +func parseHeightFromEventKey(key []byte) (int64, error) { + var ( + compositeKey, typ, eventValue string + height int64 + ) + + _, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ) + if err != nil { + return -1, fmt.Errorf("failed to parse event key: %w", err) + } + + return height, nil +} + +func parseEventSeqFromEventKey(key []byte) (int64, error) { + var ( + compositeKey, typ, eventValue string + height int64 + eventSeq int64 + ) + + remaining, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ) + if err != nil { + return 0, fmt.Errorf("failed to parse event key: %w", err) + } + + // This is done to support previous versions that did not have event sequence in their key if len(remaining) != 0 { - return "", fmt.Errorf("unexpected remainder in key: %s", remaining) + remaining, err = orderedcode.Parse(remaining, &eventSeq) + if err != nil { + return 0, fmt.Errorf("failed to parse event key: %w", err) + } + if len(remaining) != 0 { + return 0, fmt.Errorf("unexpected remainder in key: %s", remaining) + } } - return eventValue, nil + return eventSeq, nil } -func lookForHeight(conditions []syntax.Condition) (int64, bool) { +// Remove all occurrences of height equality queries except one. While we are traversing the conditions, check whether the only condition in +// addition to match events is the height equality or height range query. At the same time, if we do have a height range condition +// ignore the height equality condition. If a height equality exists, place the condition index in the query and the desired height +// into the heightInfo struct +func dedupHeight(conditions []syntax.Condition) (dedupConditions []syntax.Condition, heightInfo HeightInfo, found bool) { + heightInfo.heightEqIdx = -1 + heightRangeExists := false + var heightCondition []syntax.Condition + heightInfo.onlyHeightEq = true + heightInfo.onlyHeightRange = true for _, c := range conditions { - if c.Tag == types.BlockHeightKey && c.Op == syntax.TEq { - return int64(c.Arg.Number()), true + if c.Tag == types.BlockHeightKey { + if c.Op == syntax.TEq { + if found || heightRangeExists { + continue + } else { + heightCondition = append(heightCondition, c) + heightInfo.height = int64(c.Arg.Number()) + + found = true + } + } else { + heightInfo.onlyHeightEq = false + heightRangeExists = true + dedupConditions = append(dedupConditions, c) + } + } else { + heightInfo.onlyHeightRange = false + heightInfo.onlyHeightEq = false + dedupConditions = append(dedupConditions, c) } } + if !heightRangeExists && len(heightCondition) != 0 { + heightInfo.heightEqIdx = len(dedupConditions) + heightInfo.onlyHeightRange = false + dedupConditions = append(dedupConditions, heightCondition...) + } else { + // If we found a range make sure we set the hegiht idx to -1 as the height equality + // will be removed + heightInfo.heightEqIdx = -1 + heightInfo.height = 0 + heightInfo.onlyHeightEq = false + found = false + } + return dedupConditions, heightInfo, found +} - return 0, false +func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) bool { + if heightInfo.heightRange.Key != "" { + if !checkBounds(heightInfo.heightRange, keyHeight) { + return false + } + } else { + if heightInfo.height != 0 && keyHeight != heightInfo.height { + return false + } + } + return true } diff --git a/state/indexer/query_range.go b/state/indexer/query_range.go index c41ac2e1058..e3cfdc6fda0 100644 --- a/state/indexer/query_range.go +++ b/state/indexer/query_range.go @@ -4,6 +4,7 @@ import ( "time" "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/types" ) // QueryRanges defines a mapping between a composite event key and a QueryRange. @@ -75,8 +76,61 @@ func (qr QueryRange) UpperBoundValue() interface{} { } } -// LookForRanges returns a mapping of QueryRanges and the matching indexes in +// LookForRangesWithHeight returns a mapping of QueryRanges and the matching indexes in // the provided query conditions. +func LookForRangesWithHeight(conditions []syntax.Condition) (queryRange QueryRanges, indexes []int, heightRange QueryRange) { + queryRange = make(QueryRanges) + for i, c := range conditions { + heightKey := false + if IsRangeOperation(c.Op) { + r, ok := queryRange[c.Tag] + if !ok { + r = QueryRange{Key: c.Tag} + if c.Tag == types.BlockHeightKey || c.Tag == types.TxHeightKey { + heightRange = QueryRange{Key: c.Tag} + heightKey = true + } + } + + switch c.Op { + case syntax.TGt: + if heightKey { + heightRange.LowerBound = conditionArg(c) + } + r.LowerBound = conditionArg(c) + + case syntax.TGeq: + r.IncludeLowerBound = true + r.LowerBound = conditionArg(c) + if heightKey { + heightRange.IncludeLowerBound = true + heightRange.LowerBound = conditionArg(c) + } + + case syntax.TLt: + r.UpperBound = conditionArg(c) + if heightKey { + heightRange.UpperBound = conditionArg(c) + } + + case syntax.TLeq: + r.IncludeUpperBound = true + r.UpperBound = conditionArg(c) + if heightKey { + heightRange.IncludeUpperBound = true + heightRange.UpperBound = conditionArg(c) + } + } + + queryRange[c.Tag] = r + indexes = append(indexes, i) + } + } + + return queryRange, indexes, heightRange +} + +// Deprecated: This function is not used anymore and will be replaced with LookForRangesWithHeight func LookForRanges(conditions []syntax.Condition) (ranges QueryRanges, indexes []int) { ranges = make(QueryRanges) for i, c := range conditions { diff --git a/state/indexer/sink/psql/backport.go b/state/indexer/sink/psql/backport.go index d97cc1203c9..429cf03d310 100644 --- a/state/indexer/sink/psql/backport.go +++ b/state/indexer/sink/psql/backport.go @@ -24,7 +24,7 @@ import ( ) const ( - eventTypeFinalizeBlock = "finaliz_block" + eventTypeFinalizeBlock = "finalize_block" ) // TxIndexer returns a bridge from es to the CometBFT v0.34 transaction indexer. diff --git a/state/txindex/kv/kv.go b/state/txindex/kv/kv.go index c4240307032..17440530428 100644 --- a/state/txindex/kv/kv.go +++ b/state/txindex/kv/kv.go @@ -21,7 +21,8 @@ import ( ) const ( - tagKeySeparator = "/" + tagKeySeparator = "/" + eventSeqSeparator = "$es$" ) var _ txindex.TxIndexer = (*TxIndex)(nil) @@ -29,6 +30,8 @@ var _ txindex.TxIndexer = (*TxIndex)(nil) // TxIndex is the simplest possible indexer, backed by key-value storage (levelDB). type TxIndex struct { store dbm.DB + // Number the events in the event list + eventSeq int64 } // NewTxIndex creates new KV indexer. @@ -154,6 +157,7 @@ func (txi *TxIndex) Index(result *abci.TxResult) error { func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.Batch) error { for _, event := range result.Result.Events { + txi.eventSeq = txi.eventSeq + 1 // only index events with a non-empty type if len(event.Type) == 0 { continue @@ -171,7 +175,7 @@ func (txi *TxIndex) indexEvents(result *abci.TxResult, hash []byte, store dbm.Ba return fmt.Errorf("event type and attribute key \"%s\" is reserved; please use a different key", compositeTag) } if attr.GetIndex() { - err := store.Set(keyForEvent(compositeTag, attr.Value, result), hash) + err := store.Set(keyForEvent(compositeTag, attr.Value, result, txi.eventSeq), hash) if err != nil { return err } @@ -225,17 +229,35 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul // conditions to skip because they're handled before "everything else" skipIndexes := make([]int, 0) + var heightInfo HeightInfo + + // If we are not matching events and tx.height = 3 occurs more than once, the later value will + // overwrite the first one. + conditions, heightInfo = dedupHeight(conditions) + + if !heightInfo.onlyHeightEq { + skipIndexes = append(skipIndexes, heightInfo.heightEqIdx) + } // extract ranges // if both upper and lower bounds exist, it's better to get them in order not // no iterate over kvs that are not within range. - ranges, rangeIndexes := indexer.LookForRanges(conditions) + ranges, rangeIndexes, heightRange := indexer.LookForRangesWithHeight(conditions) + heightInfo.heightRange = heightRange if len(ranges) > 0 { skipIndexes = append(skipIndexes, rangeIndexes...) for _, qr := range ranges { + + // If we have a query range over height and want to still look for + // specific event values we do not want to simply return all + // transactios in this height range. We remember the height range info + // and pass it on to match() to take into account when processing events. + if qr.Key == types.TxHeightKey && !heightInfo.onlyHeightRange { + continue + } if !hashesInitialized { - filteredHashes = txi.matchRange(ctx, qr, startKey(qr.Key), filteredHashes, true) + filteredHashes = txi.matchRange(ctx, qr, startKey(qr.Key), filteredHashes, true, heightInfo) hashesInitialized = true // Ignore any remaining conditions if the first condition resulted @@ -244,13 +266,12 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul break } } else { - filteredHashes = txi.matchRange(ctx, qr, startKey(qr.Key), filteredHashes, false) + filteredHashes = txi.matchRange(ctx, qr, startKey(qr.Key), filteredHashes, false, heightInfo) } } } // if there is a height condition ("tx.height=3"), extract it - height := lookForHeight(conditions) // for all other conditions for i, c := range conditions { @@ -259,7 +280,7 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul } if !hashesInitialized { - filteredHashes = txi.match(ctx, c, startKeyForCondition(c, height), filteredHashes, true) + filteredHashes = txi.match(ctx, c, startKeyForCondition(c, heightInfo.height), filteredHashes, true, heightInfo) hashesInitialized = true // Ignore any remaining conditions if the first condition resulted @@ -268,19 +289,24 @@ func (txi *TxIndex) Search(ctx context.Context, q *query.Query) ([]*abci.TxResul break } } else { - filteredHashes = txi.match(ctx, c, startKeyForCondition(c, height), filteredHashes, false) + filteredHashes = txi.match(ctx, c, startKeyForCondition(c, heightInfo.height), filteredHashes, false, heightInfo) } } results := make([]*abci.TxResult, 0, len(filteredHashes)) + resultMap := make(map[string]struct{}) RESULTS_LOOP: for _, h := range filteredHashes { + res, err := txi.Get(h) if err != nil { return nil, fmt.Errorf("failed to get Tx{%X}: %w", h, err) } - results = append(results, res) - + hashString := string(h) + if _, ok := resultMap[hashString]; !ok { + resultMap[hashString] = struct{}{} + results = append(results, res) + } // Potentially exit early. select { case <-ctx.Done(): @@ -302,14 +328,9 @@ func lookForHash(conditions []syntax.Condition) (hash []byte, ok bool, err error return } -// lookForHeight returns a height if there is an "height=X" condition. -func lookForHeight(conditions []syntax.Condition) (height int64) { - for _, c := range conditions { - if c.Tag == types.TxHeightKey && c.Op == syntax.TEq { - return int64(c.Arg.Number()) - } - } - return 0 +func (txi *TxIndex) setTmpHashes(tmpHeights map[string][]byte, it dbm.Iterator) { + eventSeq := extractEventSeqFromKey(it.Key()) + tmpHeights[string(it.Value())+eventSeq] = it.Value() } // match returns all matching txs by hash that meet a given condition and start @@ -323,6 +344,7 @@ func (txi *TxIndex) match( startKeyBz []byte, filteredHashes map[string][]byte, firstRun bool, + heightInfo HeightInfo, ) map[string][]byte { // A previous match was attempted but resulted in no matches, so we return // no matches (assuming AND operand). @@ -342,8 +364,15 @@ func (txi *TxIndex) match( EQ_LOOP: for ; it.Valid(); it.Next() { - tmpHashes[string(it.Value())] = it.Value() + // If we have a height range in a query, we need only transactions + // for this height + keyHeight, err := extractHeightFromKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + + txi.setTmpHashes(tmpHashes, it) // Potentially exit early. select { case <-ctx.Done(): @@ -366,7 +395,11 @@ func (txi *TxIndex) match( EXISTS_LOOP: for ; it.Valid(); it.Next() { - tmpHashes[string(it.Value())] = it.Value() + keyHeight, err := extractHeightFromKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + txi.setTmpHashes(tmpHashes, it) // Potentially exit early. select { @@ -394,8 +427,13 @@ func (txi *TxIndex) match( if !isTagKey(it.Key()) { continue } + if strings.Contains(extractValueFromKey(it.Key()), c.Arg.Value()) { - tmpHashes[string(it.Value())] = it.Value() + keyHeight, err := extractHeightFromKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue + } + txi.setTmpHashes(tmpHashes, it) } // Potentially exit early. @@ -426,8 +464,9 @@ func (txi *TxIndex) match( // Remove/reduce matches in filteredHashes that were not found in this // match (tmpHashes). REMOVE_LOOP: - for k := range filteredHashes { - if tmpHashes[k] == nil { + for k, v := range filteredHashes { + tmpHash := tmpHashes[k] + if tmpHash == nil || !bytes.Equal(tmpHash, v) { delete(filteredHashes, k) // Potentially exit early. @@ -453,6 +492,7 @@ func (txi *TxIndex) matchRange( startKey []byte, filteredHashes map[string][]byte, firstRun bool, + heightInfo HeightInfo, ) map[string][]byte { // A previous match was attempted but resulted in no matches, so we return // no matches (assuming AND operand). @@ -461,8 +501,6 @@ func (txi *TxIndex) matchRange( } tmpHashes := make(map[string][]byte) - lowerBound := qr.LowerBoundValue() - upperBound := qr.UpperBoundValue() it, err := dbm.IteratePrefix(txi.store, startKey) if err != nil { @@ -481,18 +519,15 @@ LOOP: if err != nil { continue LOOP } + if qr.Key != types.TxHeightKey { + keyHeight, err := extractHeightFromKey(it.Key()) + if err != nil || !checkHeightConditions(heightInfo, keyHeight) { + continue LOOP + } - include := true - if lowerBound != nil && v < lowerBound.(int64) { - include = false - } - - if upperBound != nil && v > upperBound.(int64) { - include = false } - - if include { - tmpHashes[string(it.Value())] = it.Value() + if checkBounds(qr, v) { + txi.setTmpHashes(tmpHashes, it) } // XXX: passing time in a ABCI Events is not yet implemented @@ -528,8 +563,9 @@ LOOP: // Remove/reduce matches in filteredHashes that were not found in this // match (tmpHashes). REMOVE_LOOP: - for k := range filteredHashes { - if tmpHashes[k] == nil { + for k, v := range filteredHashes { + tmpHash := tmpHashes[k] + if tmpHash == nil || !bytes.Equal(tmpHashes[k], v) { delete(filteredHashes, k) // Potentially exit early. @@ -547,29 +583,64 @@ REMOVE_LOOP: // Keys func isTagKey(key []byte) bool { - return strings.Count(string(key), tagKeySeparator) == 3 + // Normally, if the event was indexed with an event sequence, the number of + // tags should 4. Alternatively it should be 3 if the event was not indexed + // with the corresponding event sequence. However, some attribute values in + // production can contain the tag separator. Therefore, the condition is >= 3. + numTags := strings.Count(string(key), tagKeySeparator) + return numTags >= 3 } +func extractHeightFromKey(key []byte) (int64, error) { + parts := strings.SplitN(string(key), tagKeySeparator, -1) + + return strconv.ParseInt(parts[len(parts)-2], 10, 64) +} func extractValueFromKey(key []byte) string { - parts := strings.SplitN(string(key), tagKeySeparator, 3) - return parts[1] + keyString := string(key) + parts := strings.SplitN(keyString, tagKeySeparator, -1) + partsLen := len(parts) + value := strings.TrimPrefix(keyString, parts[0]+tagKeySeparator) + + suffix := "" + suffixLen := 2 + + for i := 1; i <= suffixLen; i++ { + suffix = tagKeySeparator + parts[partsLen-i] + suffix + } + return strings.TrimSuffix(value, suffix) + } -func keyForEvent(key string, value string, result *abci.TxResult) []byte { - return []byte(fmt.Sprintf("%s/%s/%d/%d", +func extractEventSeqFromKey(key []byte) string { + parts := strings.SplitN(string(key), tagKeySeparator, -1) + + lastEl := parts[len(parts)-1] + + if strings.Contains(lastEl, eventSeqSeparator) { + return strings.SplitN(lastEl, eventSeqSeparator, 2)[1] + } + return "0" +} +func keyForEvent(key string, value string, result *abci.TxResult, eventSeq int64) []byte { + return []byte(fmt.Sprintf("%s/%s/%d/%d%s", key, value, result.Height, result.Index, + eventSeqSeparator+strconv.FormatInt(eventSeq, 10), )) } func keyForHeight(result *abci.TxResult) []byte { - return []byte(fmt.Sprintf("%s/%d/%d/%d", + return []byte(fmt.Sprintf("%s/%d/%d/%d%s", types.TxHeightKey, result.Height, result.Height, result.Index, + // Added to facilitate having the eventSeq in event keys + // Otherwise queries break expecting 5 entries + eventSeqSeparator+"0", )) } @@ -587,3 +658,18 @@ func startKey(fields ...interface{}) []byte { } return b.Bytes() } + +func checkBounds(ranges indexer.QueryRange, v int64) bool { + include := true + lowerBound := ranges.LowerBoundValue() + upperBound := ranges.UpperBoundValue() + if lowerBound != nil && v < lowerBound.(int64) { + include = false + } + + if upperBound != nil && v > upperBound.(int64) { + include = false + } + + return include +} diff --git a/state/txindex/kv/kv_test.go b/state/txindex/kv/kv_test.go index 7f692c01207..899a099892e 100644 --- a/state/txindex/kv/kv_test.go +++ b/state/txindex/kv/kv_test.go @@ -70,7 +70,7 @@ func TestTxSearch(t *testing.T) { txResult := txResultWithEvents([]abci.Event{ {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "1", Index: true}}}, - {Type: "account", Attributes: []abci.EventAttribute{{Key: "owner", Value: "Ivan", Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "owner", Value: "/Ivan/", Index: true}}}, {Type: "", Attributes: []abci.EventAttribute{{Key: "not_allowed", Value: "Vlad", Index: true}}}, }) hash := types.Tx(txResult.Tx).Hash() @@ -82,12 +82,16 @@ func TestTxSearch(t *testing.T) { q string resultsLength int }{ - // search by hash + // search by hash {fmt.Sprintf("tx.hash = '%X'", hash), 1}, + // search by hash (lower) + {fmt.Sprintf("tx.hash = '%x'", hash), 1}, // search by exact match (one key) {"account.number = 1", 1}, // search by exact match (two keys) - {"account.number = 1 AND account.owner = 'Ivan'", 1}, + {"account.number = 1 AND account.owner = 'Ivan'", 0}, + {"account.owner = 'Ivan' AND account.number = 1", 0}, + {"account.owner = '/Ivan/'", 1}, // search by exact match (two keys) {"account.number = 1 AND account.owner = 'Vlad'", 0}, {"account.owner = 'Vlad' AND account.number = 1", 0}, @@ -95,30 +99,41 @@ func TestTxSearch(t *testing.T) { {"account.owner = 'Vlad' AND account.number >= 1", 0}, {"account.number <= 0", 0}, {"account.number <= 0 AND account.owner = 'Ivan'", 0}, + {"account.number < 10000 AND account.owner = 'Ivan'", 0}, // search using a prefix of the stored value {"account.owner = 'Iv'", 0}, // search by range {"account.number >= 1 AND account.number <= 5", 1}, + // search by range and another key + {"account.number >= 1 AND account.owner = 'Ivan' AND account.number <= 5", 0}, // search by range (lower bound) {"account.number >= 1", 1}, // search by range (upper bound) {"account.number <= 5", 1}, + {"account.number <= 1", 1}, // search using not allowed key {"not_allowed = 'boom'", 0}, + {"not_allowed = 'Vlad'", 0}, // search for not existing tx result - {"account.number >= 2 AND account.number <= 5", 0}, + {"account.number >= 2 AND account.number <= 5 AND tx.height > 0", 0}, // search using not existing key {"account.date >= TIME 2013-05-03T14:45:00Z", 0}, // search using CONTAINS {"account.owner CONTAINS 'an'", 1}, - // search for non existing value using CONTAINS + // search for non existing value using CONTAINS {"account.owner CONTAINS 'Vlad'", 0}, + {"account.owner CONTAINS 'Ivann'", 0}, + {"account.owner CONTAINS 'IIvan'", 0}, + {"account.owner CONTAINS 'Iva n'", 0}, + {"account.owner CONTAINS ' Ivan'", 0}, + {"account.owner CONTAINS 'Ivan '", 0}, // search using the wrong key (of numeric type) using CONTAINS {"account.number CONTAINS 'Iv'", 0}, // search using EXISTS {"account.number EXISTS", 1}, // search using EXISTS for non existing key {"account.date EXISTS", 0}, + {"not_allowed EXISTS", 0}, } ctx := context.Background() @@ -139,6 +154,103 @@ func TestTxSearch(t *testing.T) { } } +func TestTxSearchEventMatch(t *testing.T) { + + indexer := NewTxIndex(db.NewMemDB()) + + txResult := txResultWithEvents([]abci.Event{ + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "1", Index: true}, {Key: "owner", Value: "Ana", Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "2", Index: true}, {Key: "owner", Value: "/Ivan/.test", Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "3", Index: false}, {Key: "owner", Value: "Mickey", Index: false}}}, + {Type: "", Attributes: []abci.EventAttribute{{Key: "not_allowed", Value: "Vlad", Index: true}}}, + }) + + err := indexer.Index(txResult) + require.NoError(t, err) + + testCases := map[string]struct { + q string + resultsLength int + }{ + "Return all events from a height": { + q: "tx.height = 1", + resultsLength: 1, + }, + "Don't match non-indexed events": { + q: "account.number = 3 AND account.owner = 'Mickey'", + resultsLength: 0, + }, + "Return all events from a height with range": { + q: "tx.height > 0", + resultsLength: 1, + }, + "Return all events from a height with range 2": { + q: "tx.height <= 1", + resultsLength: 1, + }, + "Return all events from a height (deduplicate height)": { + q: "tx.height = 1 AND tx.height = 1", + resultsLength: 1, + }, + "Match attributes with height range and event": { + q: "tx.height < 2 AND tx.height > 0 AND account.number > 0 AND account.number <= 1 AND account.owner CONTAINS 'Ana'", + resultsLength: 1, + }, + "Match attributes with multiple CONTAIN and height range": { + q: "tx.height < 2 AND tx.height > 0 AND account.number = 1 AND account.owner CONTAINS 'Ana' AND account.owner CONTAINS 'An'", + resultsLength: 1, + }, + "Match attributes with height range and event - no match": { + q: "tx.height < 2 AND tx.height > 0 AND account.number = 2 AND account.owner = 'Ana'", + resultsLength: 0, + }, + "Match attributes with event": { + q: "account.number = 2 AND account.owner = 'Ana' AND tx.height = 1", + resultsLength: 0, + }, + "Deduplication test - should return nothing if attribute repeats multiple times": { + q: "tx.height < 2 AND account.number = 3 AND account.number = 2 AND account.number = 5", + resultsLength: 0, + }, + "Deduplication test - should return nothing if attribute repeats multiple times with match events": { + q: "tx.height < 2 AND account.number = 3 AND account.number = 2 AND account.number = 5", + resultsLength: 0, + }, + " Match range with match events": { + q: "account.number < 2 AND account.owner = '/Ivan/.test'", + resultsLength: 0, + }, + " Match range with match events 2": { + q: "account.number <= 2 AND account.owner = '/Ivan/.test' AND tx.height > 0", + resultsLength: 1, + }, + " Match range with match events contains with multiple items": { + q: "account.number <= 2 AND account.owner CONTAINS '/Iv' AND account.owner CONTAINS 'an' AND tx.height = 1", + resultsLength: 1, + }, + " Match range with match events contains": { + q: "account.number <= 2 AND account.owner CONTAINS 'an' AND tx.height > 0", + resultsLength: 1, + }, + } + + ctx := context.Background() + + for _, tc := range testCases { + tc := tc + t.Run(tc.q, func(t *testing.T) { + results, err := indexer.Search(ctx, query.MustCompile(tc.q)) + assert.NoError(t, err) + + assert.Len(t, results, tc.resultsLength) + if tc.resultsLength > 0 { + for _, txr := range results { + assert.True(t, proto.Equal(txResult, txr)) + } + } + }) + } +} func TestTxSearchWithCancelation(t *testing.T) { indexer := NewTxIndex(db.NewMemDB()) @@ -242,19 +354,80 @@ func TestTxSearchOneTxWithMultipleSameTagsButDifferentValues(t *testing.T) { txResult := txResultWithEvents([]abci.Event{ {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "1", Index: true}}}, {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "2", Index: true}}}, + {Type: "account", Attributes: []abci.EventAttribute{{Key: "number", Value: "3", Index: false}}}, }) err := indexer.Index(txResult) require.NoError(t, err) + testCases := []struct { + q string + found bool + }{ + { + q: "account.number >= 1", + found: true, + }, + { + q: "account.number > 2", + found: false, + }, + { + q: "account.number >= 1 AND tx.height = 3 AND tx.height > 0", + found: true, + }, + { + q: "account.number >= 1 AND tx.height > 0 AND tx.height = 3", + found: true, + }, + + { + q: "account.number >= 1 AND tx.height = 1 AND tx.height = 2 AND tx.height = 3", + found: true, + }, + + { + q: "account.number >= 1 AND tx.height = 3 AND tx.height = 2 AND tx.height = 1", + found: false, + }, + { + q: "account.number >= 1 AND tx.height = 3", + found: false, + }, + { + q: "account.number > 1 AND tx.height < 2", + found: true, + }, + { + q: "account.number >= 2", + found: true, + }, + { + q: "account.number <= 1", + found: true, + }, + { + q: "account.number = 'something'", + found: false, + }, + { + q: "account.number CONTAINS 'bla'", + found: false, + }, + } + ctx := context.Background() - results, err := indexer.Search(ctx, query.MustCompile(`account.number >= 1`)) - assert.NoError(t, err) + for _, tc := range testCases { + results, err := indexer.Search(ctx, query.MustCompile(tc.q)) + assert.NoError(t, err) + len := 0 + if tc.found { + len = 1 + } + assert.Len(t, results, len) + assert.True(t, !tc.found || proto.Equal(txResult, results[0])) - assert.Len(t, results, 1) - for _, txr := range results { - assert.True(t, proto.Equal(txResult, txr)) } } diff --git a/state/txindex/kv/utils.go b/state/txindex/kv/utils.go index 48362bfbc2b..3f00d342be4 100644 --- a/state/txindex/kv/utils.go +++ b/state/txindex/kv/utils.go @@ -1,5 +1,22 @@ package kv +import ( + "fmt" + + cmtsyntax "github.com/cometbft/cometbft/libs/pubsub/query/syntax" + "github.com/cometbft/cometbft/state/indexer" + "github.com/cometbft/cometbft/types" + "github.com/google/orderedcode" +) + +type HeightInfo struct { + heightRange indexer.QueryRange + height int64 + heightEqIdx int + onlyHeightRange bool + onlyHeightEq bool +} + // IntInSlice returns true if a is found in the list. func intInSlice(a int, list []int) bool { for _, b := range list { @@ -9,3 +26,76 @@ func intInSlice(a int, list []int) bool { } return false } + +func ParseEventSeqFromEventKey(key []byte) (int64, error) { + var ( + compositeKey, typ, eventValue string + height int64 + eventSeq int64 + ) + + remaining, err := orderedcode.Parse(string(key), &compositeKey, &eventValue, &height, &typ, &eventSeq) + if err != nil { + return 0, fmt.Errorf("failed to parse event key: %w", err) + } + + if len(remaining) != 0 { + return 0, fmt.Errorf("unexpected remainder in key: %s", remaining) + } + + return eventSeq, nil +} +func dedupHeight(conditions []cmtsyntax.Condition) (dedupConditions []cmtsyntax.Condition, heightInfo HeightInfo) { + heightInfo.heightEqIdx = -1 + heightRangeExists := false + found := false + var heightCondition []cmtsyntax.Condition + heightInfo.onlyHeightEq = true + heightInfo.onlyHeightRange = true + for _, c := range conditions { + if c.Tag == types.TxHeightKey { + if c.Op == cmtsyntax.TEq { + if heightRangeExists || found { + continue + } else { + found = true + heightCondition = append(heightCondition, c) + heightInfo.height = int64(c.Arg.Number()) + } + } else { + heightInfo.onlyHeightEq = false + heightRangeExists = true + dedupConditions = append(dedupConditions, c) + } + } else { + heightInfo.onlyHeightRange = false + heightInfo.onlyHeightEq = false + dedupConditions = append(dedupConditions, c) + } + } + if !heightRangeExists && len(heightCondition) != 0 { + heightInfo.heightEqIdx = len(dedupConditions) + heightInfo.onlyHeightRange = false + dedupConditions = append(dedupConditions, heightCondition...) + } else { + // If we found a range make sure we set the height idx to -1 as the height equality + // will be removed + heightInfo.heightEqIdx = -1 + heightInfo.height = 0 + heightInfo.onlyHeightEq = false + } + return dedupConditions, heightInfo +} + +func checkHeightConditions(heightInfo HeightInfo, keyHeight int64) bool { + if heightInfo.heightRange.Key != "" { + if !checkBounds(heightInfo.heightRange, keyHeight) { + return false + } + } else { + if heightInfo.height != 0 && keyHeight != heightInfo.height { + return false + } + } + return true +} diff --git a/test/e2e/Makefile b/test/e2e/Makefile index 1d3109c2eec..794572d8428 100644 --- a/test/e2e/Makefile +++ b/test/e2e/Makefile @@ -1,3 +1,7 @@ +COMETBFT_BUILD_OPTIONS += badgerdb,boltdb,cleveldb,rocksdb + +include ../../common.mk + all: docker generator runner docker: @@ -10,7 +14,7 @@ docker: # order to build a binary with a CometBFT node in it (for built-in # ABCI testing). node: - go build -o build/node -tags badgerdb,boltdb,cleveldb,rocksdb ./node + go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o build/node ./node generator: go build -o build/generator ./generator diff --git a/test/e2e/generator/generate.go b/test/e2e/generator/generate.go index a382c08fc7e..f01a7e9259e 100644 --- a/test/e2e/generator/generate.go +++ b/test/e2e/generator/generate.go @@ -285,7 +285,7 @@ func generateNode( StartAt: startAt, Database: nodeDatabases.Choose(r).(string), PrivvalProtocol: nodePrivvalProtocols.Choose(r).(string), - BlockSync: nodeBlockSyncs.Choose(r).(string), + BlockSyncVersion: nodeBlockSyncs.Choose(r).(string), StateSync: nodeStateSyncs.Choose(r).(bool) && startAt > 0, PersistInterval: ptrUint64(uint64(nodePersistIntervals.Choose(r).(int))), SnapshotInterval: uint64(nodeSnapshotIntervals.Choose(r).(int)), diff --git a/test/e2e/networks/ci.toml b/test/e2e/networks/ci.toml index 264f13807f3..9fded05007a 100644 --- a/test/e2e/networks/ci.toml +++ b/test/e2e/networks/ci.toml @@ -63,7 +63,6 @@ database = "rocksdb" perturb = ["pause"] [node.validator05] -block_sync = "v0" start_at = 1005 # Becomes part of the validator set at 1010 persistent_peers = ["validator01", "full01"] database = "cleveldb" @@ -73,7 +72,6 @@ perturb = ["kill", "pause", "disconnect", "restart"] [node.full01] start_at = 1010 mode = "full" -block_sync = "v0" persistent_peers = ["validator01", "validator02", "validator03", "validator04", "validator05"] retain_blocks = 10 perturb = ["restart"] @@ -81,7 +79,6 @@ perturb = ["restart"] [node.full02] start_at = 1015 mode = "full" -block_sync = "v0" state_sync = true seeds = ["seed01"] perturb = ["restart"] diff --git a/test/e2e/pkg/manifest.go b/test/e2e/pkg/manifest.go index 5121c91ce05..eb841b78bf6 100644 --- a/test/e2e/pkg/manifest.go +++ b/test/e2e/pkg/manifest.go @@ -131,9 +131,9 @@ type ManifestNode struct { // runner will wait for the network to reach at least this block height. StartAt int64 `toml:"start_at"` - // BlockSync specifies the block sync mode: "" (disable), "v0" or "v2". - // Defaults to disabled. - BlockSync string `toml:"block_sync"` + // BlockSyncVersion specifies which version of Block Sync to use (currently + // only "v0", the default value). + BlockSyncVersion string `toml:"block_sync_version"` // StateSync enables state sync. The runner automatically configures trusted // block hashes and RPC servers. At least one node in the network must have diff --git a/test/e2e/pkg/testnet.go b/test/e2e/pkg/testnet.go index 19c8a2e2777..d0d5ae67295 100644 --- a/test/e2e/pkg/testnet.go +++ b/test/e2e/pkg/testnet.go @@ -97,7 +97,7 @@ type Node struct { IP net.IP ProxyPort uint32 StartAt int64 - BlockSync string + BlockSyncVersion string StateSync bool Database string ABCIProtocol Protocol @@ -215,7 +215,7 @@ func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureDa ABCIProtocol: Protocol(testnet.ABCIProtocol), PrivvalProtocol: ProtocolFile, StartAt: nodeManifest.StartAt, - BlockSync: nodeManifest.BlockSync, + BlockSyncVersion: nodeManifest.BlockSyncVersion, StateSync: nodeManifest.StateSync, PersistInterval: 1, SnapshotInterval: nodeManifest.SnapshotInterval, @@ -227,6 +227,9 @@ func NewTestnetFromManifest(manifest Manifest, file string, ifd InfrastructureDa if node.StartAt == testnet.InitialHeight { node.StartAt = 0 // normalize to 0 for initial nodes, since code expects this } + if node.BlockSyncVersion == "" { + node.BlockSyncVersion = "v0" + } if nodeManifest.Mode != "" { node.Mode = Mode(nodeManifest.Mode) } @@ -370,10 +373,10 @@ func (n Node) Validate(testnet Testnet) error { } } } - switch n.BlockSync { - case "", "v0": + switch n.BlockSyncVersion { + case "v0": default: - return fmt.Errorf("invalid block sync setting %q", n.BlockSync) + return fmt.Errorf("invalid block sync setting %q", n.BlockSyncVersion) } switch n.Database { case "goleveldb", "cleveldb", "boltdb", "rocksdb", "badgerdb": diff --git a/test/e2e/runner/setup.go b/test/e2e/runner/setup.go index eba167ad4e0..4fc57252aa5 100644 --- a/test/e2e/runner/setup.go +++ b/test/e2e/runner/setup.go @@ -166,6 +166,7 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { cfg.P2P.AddrBookStrict = false cfg.DBBackend = node.Database cfg.StateSync.DiscoveryTime = 5 * time.Second + cfg.BlockSync.Version = node.BlockSyncVersion switch node.ABCIProtocol { case e2e.ProtocolUNIX: @@ -212,9 +213,6 @@ func MakeConfig(node *e2e.Node) (*config.Config, error) { return nil, fmt.Errorf("unexpected mode %q", node.Mode) } - cfg.BlockSyncMode = true - cfg.BlockSync.Version = "v0" - if node.StateSync { cfg.StateSync.Enable = true cfg.StateSync.RPCServers = []string{}